<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert! | Von Brank</title><meta name="keywords" content="教程,课程笔记,Web开发,JavaScript"><meta name="author" content="Von Brank"><meta name="copyright" content="Von Brank"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="The modern JavaScript course for everyone! Master JavaScript with projects, challenges and theory. Many courses in one!">
<meta property="og:type" content="article">
<meta property="og:title" content="【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!">
<meta property="og:url" content="https://vonbrank.github.io/archives/udemy-note-the-complete-javascript-course/index.html">
<meta property="og:site_name" content="Von Brank">
<meta property="og:description" content="The modern JavaScript course for everyone! Master JavaScript with projects, challenges and theory. Many courses in one!">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://s2.loli.net/2022/01/07/IpZeyLJzvVwbO7A.jpg">
<meta property="article:published_time" content="2022-01-07T16:13:32.000Z">
<meta property="article:modified_time" content="2022-05-17T05:59:38.868Z">
<meta property="article:author" content="Von Brank">
<meta property="article:tag" content="教程">
<meta property="article:tag" content="课程笔记">
<meta property="article:tag" content="Web开发">
<meta property="article:tag" content="JavaScript">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://s2.loli.net/2022/01/07/IpZeyLJzvVwbO7A.jpg"><link rel="shortcut icon" href="https://s2.loli.net/2022/01/08/s8FYlS5uPrtichT.jpg"><link rel="canonical" href="https://vonbrank.github.io/archives/udemy-note-the-complete-javascript-course/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"简"},
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#121212","position":"bottom-left"},
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: '【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-05-17 13:59:38'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          const now = new Date()
          const hour = now.getHours()
          const isNight = hour <= 6 || hour >= 18
          if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
          else if (t === 'light') activateLightMode()
          else activateDarkMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if (GLOBAL_CONFIG_SITE.isHome && /iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="Von Brank" type="application/atom+xml">
</head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://s2.loli.net/2022/01/08/s8FYlS5uPrtichT.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">46</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">25</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/categories/"><div class="headline">分类</div><div class="length-num">19</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/comments/"><i class="fa-fw fas fa-comments"></i><span> 评论</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-tools"></i><span> 工具</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="https://vonbrank.github.io/hit-introduction-to-discrete-mathematics/"><i class="fa-fw fas fa-less-than-equal"></i><span> 《离散数学引论》答案补充</span></a></li><li><a class="site-page child" href="https://vonbrank.github.io/my-tech-companies-website/"><i class="fa-fw fas fa-server"></i><span> 科技公司网页模仿</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://s2.loli.net/2022/01/07/IpZeyLJzvVwbO7A.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Von Brank</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/comments/"><i class="fa-fw fas fa-comments"></i><span> 评论</span></a></div><div class="menus_item"><a class="site-page" href="javascript:void(0);"><i class="fa-fw fas fa-tools"></i><span> 工具</span><i class="fas fa-chevron-down expand"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="https://vonbrank.github.io/hit-introduction-to-discrete-mathematics/"><i class="fa-fw fas fa-less-than-equal"></i><span> 《离散数学引论》答案补充</span></a></li><li><a class="site-page child" href="https://vonbrank.github.io/my-tech-companies-website/"><i class="fa-fw fas fa-server"></i><span> 科技公司网页模仿</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-01-07T16:13:32.000Z" title="发表于 2022-01-08 00:13:32">2022-01-08</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-05-17T05:59:38.868Z" title="更新于 2022-05-17 13:59:38">2022-05-17</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/JavaScript/">JavaScript</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">9.5k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>42分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="JavaScript-基础">JavaScript 基础</h2>
<h3 id="数据、运算与判断">数据、运算与判断</h3>
<h4 id="隐式转换">隐式转换</h4>
<p>当运算符两端数据类型不同时，如 <code>'1' + 2</code> ，若没有进行显式类型转换，则 JavaScript 解释器将对其做隐式类型转换。JavaScripit 的隐式类型转换常常让初学者感到疑惑，这是因为 JavaScript 不同基本数据类型之间没有明确的优先级关系，不存在所谓的“低级转向高级”，也不存在类似 C/C++ 的重载运算符操作；此外，优先级相同的运算符如 <code>+</code> 和 <code>-</code> 可导致截然不同的隐式转换逻辑。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/07/tnfHlk5C2ewQVx1.jpg" alt="post-udemy-javascript-js-vs-christianity"></p>
<p>即便如此，JavaScript 的的隐式转换规则仍然有迹可循。</p>
<ul>
<li>
<p><code>+</code> 运算可将两侧变量隐式转换为 <code>String</code> 类型：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;12&quot;</span> + <span class="number">34</span>; <span class="comment">//  -&gt;  &#x27;1234&#x27;</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>-</code> 运算可将两侧变量隐式转换为 <code>Number</code> 类型：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;12&quot;</span> - <span class="number">34</span>; <span class="comment">//  -&gt;  -22</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>&lt;=, &lt;, &gt;=, &gt;</code> 可将两侧变量隐式转换为 <code>Number</code> 类型：</p>
</li>
<li>
<p>同级运算与隐式转换从左到右顺次进行：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">5</span> + <span class="number">6</span> + <span class="string">&quot;4&quot;</span> + <span class="number">9</span> - <span class="number">4</span> - <span class="number">2</span>; <span class="comment">//  -&gt;  1143</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="函数与对象">函数与对象</h3>
<h4 id="函数的三种形式">函数的三种形式</h4>
<p>JavaScript 有三种主要的函数表示形式，假设我们要定义一个函数，传入一个参数 <code>population</code> ，返回传入人口参数占世界的百分比，三种形式如下所示：</p>
<ul>
<li>
<p>声明形式（Declaration）</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">percentageOfWorld1</span>(<span class="params">population</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> totalPopulationOfWorld = <span class="number">7900</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;(population / totalPopulationOfWorld) * <span class="number">100</span>&#125;</span>%`</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>匿名形式（Expressions）</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> percentageOfWorld2 = <span class="function"><span class="keyword">function</span> (<span class="params">population</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> totalPopulationOfWorld = <span class="number">7900</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;(population / totalPopulationOfWorld) * <span class="number">100</span>&#125;</span>%`</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>箭头函数（Arrow Function）</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> percentageOfWorld3 = <span class="function">(<span class="params">population</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> totalPopulationOfWorld = <span class="number">7900</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;(population / totalPopulationOfWorld) * <span class="number">100</span>&#125;</span>%`</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>设全球总人口为 <code>7900M</code> ，中国人口为 <code>1441M</code> ，调用结果如下所示：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">percentageOfWorld1(<span class="number">1441</span>); <span class="comment">//  -&gt;  18.240506329113924%</span></span><br><span class="line">percentageOfWorld2(<span class="number">1441</span>); <span class="comment">//  -&gt;  18.240506329113924%</span></span><br><span class="line">percentageOfWorld3(<span class="number">1441</span>); <span class="comment">//  -&gt;  18.240506329113924%</span></span><br></pre></td></tr></table></figure>
<h4 id="箭头函数的不适用场景">箭头函数的不适用场景</h4>
<ul>
<li>
<p>函数作为对象属性时，应该使用匿名函数，而不是箭头函数，如：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> myCountry = &#123;</span><br><span class="line">    country: <span class="string">&quot;China&quot;</span>,</span><br><span class="line">    capital: <span class="string">&quot;Beijing&quot;</span>,</span><br><span class="line">    language: <span class="string">&quot;Chinese&quot;</span>,</span><br><span class="line">    population: <span class="number">1300</span>,</span><br><span class="line">    neighbours: [<span class="string">&quot;Japan&quot;</span>, <span class="string">&quot;Russia&quot;</span>, <span class="string">&quot;Korea&quot;</span>, <span class="string">&quot;India&quot;</span>],</span><br><span class="line">    describe: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(</span><br><span class="line">            <span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.country&#125;</span> has <span class="subst">$&#123;<span class="built_in">this</span>.population&#125;</span> million <span class="subst">$&#123;<span class="built_in">this</span>.language&#125;</span>-speaking people, <span class="subst">$&#123;<span class="built_in">this</span>.neighbours.length&#125;</span> neighbouring countries and a capital called <span class="subst">$&#123;<span class="built_in">this</span>.capital&#125;</span>`</span></span><br><span class="line">        );</span><br><span class="line">    &#125;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 不应该使用箭头函数</span></span><br><span class="line">    <span class="comment">// describe: () =&gt; &#123;</span></span><br><span class="line">    <span class="comment">//     console.log(</span></span><br><span class="line">    <span class="comment">//         `$&#123;this.country&#125; has $&#123;this.population&#125; million $&#123;this.language&#125;-speaking people, $&#123;this.neighbours.length&#125; neighbouring countries and a capital called $&#123;this.capital&#125;.`</span></span><br><span class="line">    <span class="comment">//     );</span></span><br><span class="line">    <span class="comment">// &#125;,</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>箭头函数作为对象属性时， <code>this</code> 并非指向对象本身，原型链失效，从而使得用 <code>this</code> 访问对象属性将导致意外情况。</p>
</li>
</ul>
<h3 id="数组与循环">数组与循环</h3>
<h2 id="DOM-树与事件处理">DOM 树与事件处理</h2>
<p>HTML 文件在浏览器内被解析为 DOM 树。</p>
<h3 id="获取-HTML-元素">获取 HTML 元素</h3>
<p>浏览器的 Web API 提供了 <code>document</code> 对象，用于对 DOM 树进行操作。</p>
<ul>
<li>
<p><code>document.querySelector()</code> 可通过传入 CSS 选择器，选择符合要求的第一个元素节点，返回对该元素对象的引用：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> body = <span class="built_in">document</span>.querySelector(<span class="string">&quot;body&quot;</span>); <span class="comment">//  选择 body 元素，</span></span><br><span class="line"><span class="keyword">const</span> guess = <span class="built_in">document</span>.querySelector(<span class="string">&quot;.guess&quot;</span>); <span class="comment">// 选择第一个 class=&quot;guess&quot; 的元素</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>document.querySelectorAll()</code> 返回符合选择器的所有元素节点，即一个元素对象数组。</p>
</li>
</ul>
<h3 id="监听点击事件">监听点击事件</h3>
<ul>
<li>
<p><code>element.addEventListener()</code> 为 <code>element</code> 元素对象注册一个监听器，当元素符合监听行为时，立刻执行传入的函数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 为 check 元素注册点击事件的监听器</span></span><br><span class="line">check.addEventListener(<span class="string">&quot;click&quot;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    statements...</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p>注意到传入的第二个参数是一个函数，这里体现了 JavaScript 中函数和其他对象（<code>object</code>）地位等同，函数的内容就是其本身 <code>object</code> 的值。</p>
</li>
</ul>
<h3 id="编辑元素-CSS-样式">编辑元素 CSS 样式</h3>
<ul>
<li>
<p><code>element.style.property</code> 返回对元素某个样式的引用：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> message = <span class="built_in">document</span>.querySelector(<span class="string">&quot;.message&quot;</span>);</span><br><span class="line">message.style.fontSize = <span class="string">&quot;2rem&quot;</span>;</span><br></pre></td></tr></table></figure>
<p>注意到 CSS 中字体大小属性为 <code>font-size</code> ，但是这在 JavaScript 中不是合法的变量名，需改为驼峰命名法的 <code>fontSize</code>。</p>
</li>
</ul>
<h3 id="处理元素的-class">处理元素的 class</h3>
<ul>
<li>
<p><code>element.classList</code> 返回元素的 <code>class</code> 列表，可使用 <code>.add()</code> 与 <code>.remove()</code> 对其进行增删；使用 <code>.toggle()</code> 可实现在没有该类时添加该类，有该类时移除该类；<code>.contains()</code> 判断是否存在某个类：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> modal = <span class="built_in">document</span>.querySelector(<span class="string">&quot;.modal&quot;</span>);</span><br><span class="line">modal.classList.add(<span class="string">&quot;hidden&quot;</span>); <span class="comment">//添加 hidden 类</span></span><br><span class="line">modal.classList.remove(<span class="string">&quot;hidden&quot;</span>); <span class="comment">//移除 hidden 类</span></span><br><span class="line">modal.classList.toggle(<span class="string">&quot;hidden&quot;</span>); <span class="comment">//检查是否存在 hidden 类，若不存在则添加，否则移除</span></span><br><span class="line">modal.classList.contains(<span class="string">&quot;hidden&quot;</span>); <span class="comment">//检查是否存在 hidden 类</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>element.className.includes(&quot;class&quot;)&quot;</code> 同样返回是否存在该类。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> modal = <span class="built_in">document</span>.querySelector(<span class="string">&quot;.modal&quot;</span>);</span><br><span class="line">modal.className.includes(<span class="string">&quot;hidden&quot;</span>); <span class="comment">//检查是否存在 hidden 类</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="JavaScript-幕后解析">JavaScript 幕后解析</h2>
<h3 id="总览">总览</h3>
<p>现代 JavaScript 语言拥有如下特性</p>
<ul>
<li>是一门高级语言</li>
<li>支持内存回收</li>
<li>解释型或 JIT 编译型语言</li>
<li>支持多种编程范式：面向过程、面向对象、函数式</li>
<li>基于原型与面向对象</li>
<li>函数与变量同级</li>
<li>动态类型</li>
<li>单线程</li>
<li>非阻塞性事件循环</li>
</ul>
<h3 id="JavaScript-引擎与运行环境">JavaScript 引擎与运行环境</h3>
<ul>
<li>
<p>JavaScript 引擎主要由两个部分组成：调用栈和堆。</p>
<p>调用栈主要用于存储函数执行的上下文，堆用于存储引用指向的数据实例。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/t3OWJUbCNAM5as7.jpg" alt="note-javascript-engine"></p>
</li>
<li>
<p>”JavaScript 是一门解释型“语言可能是 JavaScript 普遍存在的最大认知误区之一。初出茅庐的 JavaScript 确实如此，但现代浏览器或形如 Node.js 的运行环境使用的是 JIT（Just-in-time）方法。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/6gstqolmwpikK4A.jpg" alt="note-javascript-jit"></p>
<p>在 JIT 流程中，JavaScript 代码会先被转换成抽象语法树（AST），使用解释器执行，而 Baselines compiler 与 Optimization compiler 会在后台评估每行代码的执行命中率，逐渐执行与传统编译型语言类似的工作，提高运行效率。</p>
</li>
<li>
<p>浏览器端的 JavaScript 的运行环境由 JavaScript 引擎，浏览器提供的 Web API ，回调队列构成。JavaScript 引擎和回调队列组成非阻塞性事件循环。 Node.js 中的运行环境则是移除了 Web API ，并添加了一些 Native 层的内容。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/TI5jdBVkJflS1p8.jpg" alt="note-javascript-browser-runtime"></p>
</li>
</ul>
<h3 id="执行上下文">执行上下文</h3>
<p>JavaScript 的执行上下文是一个很抽象的概念，其相当于代码执行的一个“环境”，存储了代码执行所需的一些信息，通常包括：</p>
<ul>
<li>环境中的变量</li>
<li>作用域链</li>
<li><code>this</code> 关键字对象</li>
</ul>
<p>这好比享用外卖 Pizza 时，我们不仅需要从包装盒里取出 Pizza 本身，还需要拿出一次性餐具，必要时取出收据进行检查。包装盒就是“上下文”，Pizza 是我们要执行的对象，餐具和收据是环境中的变量。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/8XmixJAZG6ubSwP.jpg" alt="note-javascript-execution-context"></p>
<p>运行在 JavaScript 最外层的代码所处的是全局上下文（Global execution context），在编译完成后被创建，并执行其中的代码，之后等待事件循环的回调函数。</p>
<p>此外，每个函数的执行都会创建自己的上下文。</p>
<h3 id="调用栈、作用域与作用域链">调用栈、作用域与作用域链</h3>
<p>函数的每一次执行都会创建自己的上下文，并压入调用栈中，执行完后弹出栈顶，并回到调用这个函数的地方。这种设计可以防止上下文丢失。</p>
<p>作用域指的是变量可被获得（access）的区域（scope），JavaScript 的作用域分为全局作用域、函数作用域、块级作用域。内部作用域可以访问外部作用域的变量，反之未然 ，这便是作用域链。</p>
<p><code>var</code> 变量是函数级作用域的，<code>let</code> 和 <code>const</code> 均是块级。</p>
<p>作用域链和调用栈没有任何关系。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/Mk15j4fSBDigosC.jpg" alt="note-javascript-call-stack-and-scope-chain"></p>
<h3 id="声明提升与临时静默域（TDZ）">声明提升与临时静默域（TDZ）</h3>
<p>函数的声明提升，即运行调用写在声明之前，是高级语言解决函数相互引用问题的常见特性。而 <code>var</code> 类型也变量允许声明则是 JavaScript 早期为支持 <code>first-class function</code> 所产生的历史遗留问题。</p>
<p><code>var</code> 变量在被声明前引用的值是 <code>undefined</code> ，表面上看是 JavaScript 将声明提前了，其实不然。实际上 JavaScript 在每个执行上下文之前都会扫描整个作用域，检查那些变量需要做声明提升。</p>
<table>
<thead>
<tr>
<th></th>
<th>是否声明提升</th>
<th>初值</th>
<th>作用域</th>
</tr>
</thead>
<tbody>
<tr>
<td>函数变量</td>
<td>是</td>
<td>函数值本身</td>
<td>块级</td>
</tr>
<tr>
<td><code>var</code> 变量</td>
<td>是</td>
<td><code>undefined</code></td>
<td>函数级</td>
</tr>
<tr>
<td><code>let</code> 和 <code>const</code> 变量</td>
<td>否</td>
<td><code>&lt;uninitialized&gt;</code>，TDZ</td>
<td>块级</td>
</tr>
<tr>
<td>函数表达式和箭头函数</td>
<td>取决于是 <code>var</code> ，<code>let</code> 还是 <code>const</code></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/LMGt75NPgQq2RyW.jpg" alt="note-javascript-tdz"></p>
<p><code>var</code> 类型变量、包括函数在内当前上下文内的对象都是父对象的成员变量</p>
<h3 id="this-关键字"><code>this</code> 关键字</h3>
<p><code>this</code> 是每个上下文创建的特殊变量，最常见的用法是，对象的成员函数作用域内的 <code>this</code> 指向对象本身。</p>
<p>其他情况下 <code>this</code> 的指向如表所示。</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>指向</th>
</tr>
</thead>
<tbody>
<tr>
<td>方法</td>
<td>调用之的对象</td>
</tr>
<tr>
<td>单独调用函数</td>
<td><code>undefined</code>（严格模式下）</td>
</tr>
<tr>
<td>箭头函数</td>
<td>外部作用域的 <code>this</code></td>
</tr>
<tr>
<td>监听器</td>
<td>监听到的 DOM 元素</td>
</tr>
</tbody>
</table>
<h3 id="正则函数与箭头函数">正则函数与箭头函数</h3>
<p>声明式函数与匿名函数被称为正则函数（regular function），其与箭头函数的区别主要在 <code>this</code> 和 <code>arguments</code> 变量上。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> vonbrank = &#123;</span><br><span class="line">    year: <span class="number">2001</span>,</span><br><span class="line">    calcAge: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="built_in">this</span>.year);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> foo1 = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="built_in">this</span>.year);</span><br><span class="line">            <span class="comment">// this == undefined，会报 reference error</span></span><br><span class="line">        &#125;;</span><br><span class="line">        foo1();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> self = <span class="built_in">this</span>;</span><br><span class="line">        <span class="keyword">const</span> foo1 = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="built_in">this</span> = self;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="built_in">this</span>.year);</span><br><span class="line">            <span class="comment">// 将外部的 this 保存为 self 传进来，可以正常运行</span></span><br><span class="line">        &#125;;</span><br><span class="line">        foo2();</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> foo3 = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="built_in">this</span>);</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="built_in">this</span>.year);</span><br><span class="line">            <span class="comment">// 箭头函数本身不不包含 this 对象，沿着作用域链网上找能找到 calcAge 的 this ，即 vonbrank</span></span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        foo3();</span><br><span class="line">    &#125;,</span><br><span class="line">    greeting: <span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="built_in">this</span>),</span><br><span class="line">    <span class="comment">//同样的 greeting 内没有 this 参数，沿作用域链向上找到全局作用域，而全局作用域也没有 this 对象，所以输出 undefined</span></span><br><span class="line">&#125;;</span><br><span class="line">vonbrank.calcAge();</span><br><span class="line">vonbrank.greeting();</span><br></pre></td></tr></table></figure>
<p>正则函数拥有 <code>arguments</code> 变量，这是传入参数构成的数组。箭头函数则没有。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> addExpr = <span class="function"><span class="keyword">function</span> (<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">arguments</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> addArrow = <span class="function">(<span class="params">a, b</span>) =&gt;</span> <span class="built_in">console</span>.log(<span class="built_in">arguments</span>);</span><br><span class="line"></span><br><span class="line">addExpr(<span class="number">2</span>, <span class="number">5</span>); <span class="comment">//[2, 5]</span></span><br><span class="line">addArrow(<span class="number">2</span>, <span class="number">5</span>); <span class="comment">//reference error</span></span><br></pre></td></tr></table></figure>
<h3 id="原始类型与对象引用">原始类型与对象引用</h3>
<p>JavaScript 中的原始类型（primitive types）有：</p>
<ul>
<li>Number</li>
<li>String</li>
<li>Boolean</li>
<li>Undefined</li>
<li>Null</li>
<li>Symbol</li>
<li>BigInt</li>
</ul>
<p>对象类型（reference types）有：</p>
<ul>
<li>Object 字面量</li>
<li>数组</li>
<li>函数</li>
</ul>
<p>等。</p>
<p>原始类型和对象引用的名称都存储在 JavaScript 引擎的 Identifier 中。</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/15/lfzIWQMVyEbUwsK.jpg" alt="note-javascript-primitive-objects"></p>
<p>原始类型的数据值存储在调用栈（CALL STACK）的上下文中，每次修改时，由于调用栈中的数据一旦创建便不可修改。因此会在调用栈中开辟新的内存，存储修改后的值，同时 Identifier 令名称指向新的内存。这便解释了如下代码。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> age = <span class="number">30</span>;</span><br><span class="line"><span class="keyword">const</span> oldAge = age;</span><br><span class="line">age = <span class="number">27</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(age); <span class="comment">//27</span></span><br><span class="line"><span class="built_in">console</span>.log(oldAge); <span class="comment">//30</span></span><br></pre></td></tr></table></figure>
<p>数据引用会将数据实际存储在堆区（HEAP），栈区存储指向堆区实例的地址（引用），多个变量名指向同一个引用，修改时也会改变堆区同一个地址的内容。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> me = &#123;</span><br><span class="line">    name: <span class="string">&quot;Jonas&quot;</span>,</span><br><span class="line">    age: <span class="number">30</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> friend = me;</span><br><span class="line">friend.age = <span class="number">27</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(friend.age); <span class="comment">//27</span></span><br><span class="line"><span class="built_in">console</span>.log(me.age); <span class="comment">//27</span></span><br></pre></td></tr></table></figure>
<p>如果确实要创建两个值相同，引用不同的对象，可以使用 <code>Object.assign()</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> source = &#123; <span class="attr">b</span>: <span class="number">4</span>, <span class="attr">c</span>: <span class="number">5</span> &#125;;</span><br><span class="line"><span class="keyword">const</span> newSource = <span class="built_in">Object</span>.assign(&#123;&#125;, source);</span><br><span class="line"><span class="built_in">console</span>.log(newSource); <span class="comment">//&#123; b: 4, c: 5 &#125;</span></span><br></pre></td></tr></table></figure>
<p>但这样只是浅度拷贝，即如果原对象有对象成员，拷贝结果仍然是该成员的引用。实现引用对象的深度拷贝很多时候是一件比较困难的事情，原生 JavaScript 并没有提供深度拷贝方法，可以自己手动实现，或调用外部库。</p>
<h2 id="JavaScript-高级编程">JavaScript 高级编程</h2>
<p>为方便模拟实际项目的情况，本节默认全局上下文已执行以下语句：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&quot;use strict&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Data needed for a later exercise</span></span><br><span class="line"><span class="keyword">const</span> flights =</span><br><span class="line">    <span class="string">&quot;_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Data needed for first part of the section</span></span><br><span class="line"><span class="keyword">const</span> restaurant = &#123;</span><br><span class="line">    name: <span class="string">&quot;Classico Italiano&quot;</span>,</span><br><span class="line">    location: <span class="string">&quot;Via Angelo Tavanti 23, Firenze, Italy&quot;</span>,</span><br><span class="line">    categories: [<span class="string">&quot;Italian&quot;</span>, <span class="string">&quot;Pizzeria&quot;</span>, <span class="string">&quot;Vegetarian&quot;</span>, <span class="string">&quot;Organic&quot;</span>],</span><br><span class="line">    starterMenu: [<span class="string">&quot;Focaccia&quot;</span>, <span class="string">&quot;Bruschetta&quot;</span>, <span class="string">&quot;Garlic Bread&quot;</span>, <span class="string">&quot;Caprese Salad&quot;</span>],</span><br><span class="line">    mainMenu: [<span class="string">&quot;Pizza&quot;</span>, <span class="string">&quot;Pasta&quot;</span>, <span class="string">&quot;Risotto&quot;</span>],</span><br><span class="line"></span><br><span class="line">    openingHours: &#123;</span><br><span class="line">        thu: &#123;</span><br><span class="line">            open: <span class="number">12</span>,</span><br><span class="line">            close: <span class="number">22</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">        fri: &#123;</span><br><span class="line">            open: <span class="number">11</span>,</span><br><span class="line">            close: <span class="number">23</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">        sat: &#123;</span><br><span class="line">            open: <span class="number">0</span>, <span class="comment">// Open 24 hours</span></span><br><span class="line">            close: <span class="number">24</span>,</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<h3 id="解构赋值">解构赋值</h3>
<ul>
<li>
<p>数组解构赋值</p>
<p>数组解构赋值可以实现将数组批量赋值给一组变量。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];</span><br><span class="line"><span class="keyword">const</span> [x, y, z] = arr;</span><br><span class="line"><span class="built_in">console</span>.log(x, y, z); <span class="comment">//2 3 4</span></span><br></pre></td></tr></table></figure>
<p>还可以跳过某些元素。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];</span><br><span class="line"><span class="keyword">const</span> [x, , y] = arr;</span><br><span class="line"><span class="built_in">console</span>.log(x, y); <span class="comment">//2 4</span></span><br></pre></td></tr></table></figure>
<p>用于快速交换变量的值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> x = <span class="number">1</span>,</span><br><span class="line">    y = <span class="number">2</span>;</span><br><span class="line">[x, y] = [y, x];</span><br><span class="line"><span class="built_in">console</span>.log(x, y); <span class="comment">//2 1</span></span><br></pre></td></tr></table></figure>
<p>接受函数返回多个变量。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> order = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> [<span class="number">2</span>, <span class="number">5</span>];</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">let</span> [x, y] = order();</span><br><span class="line"><span class="built_in">console</span>.log(x, y); <span class="comment">//2 5</span></span><br></pre></td></tr></table></figure>
<p>嵌套解构赋值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> nest = [<span class="number">2</span>, <span class="number">4</span>, [<span class="number">5</span>, <span class="number">6</span>]];</span><br><span class="line"><span class="keyword">const</span> [i, , [j, k]] = nest;</span><br><span class="line"><span class="built_in">console</span>.log(i, j, k);</span><br></pre></td></tr></table></figure>
<p>默认解构赋值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [p = <span class="number">1</span>, q = <span class="number">1</span>, r] = [<span class="number">8</span>, <span class="number">9</span>];</span><br><span class="line"><span class="built_in">console</span>.log(p, q, r); <span class="comment">//8 9 undefined</span></span><br><span class="line">[p = <span class="number">1</span>, q = <span class="number">1</span>, r = <span class="number">1</span>] = [<span class="number">8</span>, <span class="number">9</span>];</span><br><span class="line"><span class="built_in">console</span>.log(p, q, r); <span class="comment">//8 9 1</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p>对象解构赋值</p>
<p>对象解构赋值和数组类似，括号变成花括号。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; name, openingHours, categories &#125; = restaurant;</span><br><span class="line"><span class="built_in">console</span>.log(name, openingHours, categories);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Classico </span></span><br><span class="line"><span class="comment">Italiano &#123;</span></span><br><span class="line"><span class="comment">    thu: &#123; open: 12, close: 22 &#125;,</span></span><br><span class="line"><span class="comment">    fri: &#123; open: 11, close: 23 &#125;,</span></span><br><span class="line"><span class="comment">    sat: &#123; open: 0, close: 24 &#125;</span></span><br><span class="line"><span class="comment">&#125; </span></span><br><span class="line"><span class="comment">[ &#x27;Italian&#x27;, &#x27;Pizzeria&#x27;, &#x27;Vegetarian&#x27;, &#x27;Organic&#x27; ]</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>使用不同的变量名。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123;</span><br><span class="line">    name: restaurantName,</span><br><span class="line">    openingHours: hours,</span><br><span class="line">    categories: tags,</span><br><span class="line">&#125; = restaurant;</span><br><span class="line"><span class="built_in">console</span>.log(restaurantName, hours, tags);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Classico </span></span><br><span class="line"><span class="comment">Italiano &#123;</span></span><br><span class="line"><span class="comment">    thu: &#123; open: 12, close: 22 &#125;,</span></span><br><span class="line"><span class="comment">    fri: &#123; open: 11, close: 23 &#125;,</span></span><br><span class="line"><span class="comment">    sat: &#123; open: 0, close: 24 &#125;</span></span><br><span class="line"><span class="comment">&#125; </span></span><br><span class="line"><span class="comment">[ &#x27;Italian&#x27;, &#x27;Pizzeria&#x27;, &#x27;Vegetarian&#x27;, &#x27;Organic&#x27; ]</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>设置默认值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; menu = [], <span class="attr">starterMenu</span>: starters = [] &#125; = restaurant;</span><br><span class="line"><span class="built_in">console</span>.log(menu, starters); <span class="comment">//[] [ &#x27;Focaccia&#x27;, &#x27;Bruschetta&#x27;, &#x27;Garlic Bread&#x27;, &#x27;Caprese Salad&#x27; ]</span></span><br></pre></td></tr></table></figure>
<p>多个变量重新赋值，注意，由于 JavaScript 会将大括号开头的行视作一个新的作用域，因此需要用括号括起来防止歧义。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">111</span>;</span><br><span class="line"><span class="keyword">let</span> b = <span class="number">999</span>;</span><br><span class="line"><span class="keyword">const</span> obj = &#123; <span class="attr">a</span>: <span class="number">23</span>, <span class="attr">b</span>: <span class="number">7</span>, <span class="attr">c</span>: <span class="number">14</span> &#125;;</span><br><span class="line"></span><br><span class="line">(&#123; a, b &#125; = obj);</span><br><span class="line"><span class="built_in">console</span>.log(a, b);</span><br></pre></td></tr></table></figure>
<p>子对象解构赋值。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; openingHours &#125; = restaurant;</span><br><span class="line"><span class="keyword">const</span> &#123;</span><br><span class="line">    fri: &#123; open, close &#125;,</span><br><span class="line">&#125; = openingHours;</span><br><span class="line"><span class="built_in">console</span>.log(open, close); <span class="comment">// 11 23</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//依然可以使用类似方法重命名，节省大量代码</span></span><br><span class="line"><span class="keyword">const</span> &#123;</span><br><span class="line">    fri: &#123; <span class="attr">open</span>: o, <span class="attr">close</span>: c &#125;,</span><br><span class="line">&#125; = openingHours;</span><br><span class="line"><span class="built_in">console</span>.log(o, c); <span class="comment">// 11 23</span></span><br></pre></td></tr></table></figure>
<p>作为函数参数。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">restaurant.orderDelivery = <span class="function"><span class="keyword">function</span> (<span class="params">&#123;</span></span></span><br><span class="line"><span class="function"><span class="params">    starterIndex = <span class="number">1</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    mainIndex = <span class="number">0</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    time = <span class="string">&quot;20:00&quot;</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    address,</span></span></span><br><span class="line"><span class="function"><span class="params">&#125;</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(starterIndex, mainIndex, time, address);</span><br><span class="line">&#125;;</span><br><span class="line">restaurant.orderDelivery(&#123;</span><br><span class="line">    time: <span class="string">&quot;22:30&quot;</span>,</span><br><span class="line">    address: <span class="string">&quot;Via del sole, 21&quot;</span>,</span><br><span class="line">    mainIndex: <span class="number">2</span>,</span><br><span class="line">    starterIndex: <span class="number">2</span>,</span><br><span class="line">&#125;); <span class="comment">//2 2 22:30 Via del sole, 21</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="扩张运算符-与-rest-参数运算符">扩张运算符 <code>...</code> 与 <code>rest</code> 参数运算符</h3>
<p>JavaScript 中的 <code>...</code> 运算符用于将可迭代对象（包括数组，字符串，<code>map</code>，<code>set</code> 等）分解为一组单个元素，这些元素是原对象的浅层拷贝。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> name = <span class="string">&quot;vonbrank&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> letters = [...name, <span class="string">&quot; &quot;</span>, <span class="string">&quot;.s&quot;</span>];</span><br><span class="line"><span class="built_in">console</span>.log(letters);</span><br><span class="line"><span class="comment">//[&#x27;v&#x27;, &#x27;o&#x27;, &#x27;n&#x27;, &#x27;b&#x27;, &#x27;r&#x27;, &#x27;a&#x27;, &#x27;n&#x27;, &#x27;k&#x27;, &#x27; &#x27;, &#x27;.s&#x27;]</span></span><br></pre></td></tr></table></figure>
<p>合并数组。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>];</span><br><span class="line"><span class="keyword">const</span> newArr = [<span class="number">1</span>, <span class="number">2</span>, ...arr];</span><br><span class="line"><span class="built_in">console</span>.log(newArr); <span class="comment">//[1, 2, 7, 8, 9]</span></span><br><span class="line"><span class="built_in">console</span>.log(...arr); <span class="comment">//[7, 8, 9]</span></span><br></pre></td></tr></table></figure>
<p>作为函数参数传递。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">restaurant.orderPasta = <span class="function"><span class="keyword">function</span> (<span class="params">ing1, ing2, ing3</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(ing1, ing2, ing3);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ingredients = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>];</span><br><span class="line">restaurant.orderPasta(...ingredients); <span class="comment">// a b c</span></span><br></pre></td></tr></table></figure>
<p><code>rest</code> 参数运算符和 <code>...</code> 运算符写法几乎一致，但是却是执行相反的操作。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [a, b, ...others] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];</span><br><span class="line"><span class="built_in">console</span>.log(a, b, others); <span class="comment">//1 2 [ 3, 4, 5 ]</span></span><br></pre></td></tr></table></figure>
<p>与 <code>...</code> 运算符配合使用：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [pizza, , risotto, ...otherFoods] = [</span><br><span class="line">    ...restaurant.mainMenu,</span><br><span class="line">    ...restaurant.starterMenu,</span><br><span class="line">];</span><br><span class="line"><span class="built_in">console</span>.log(pizza, risotto, otherFoods); <span class="comment">//Pizza Risotto [ &#x27;Focaccia&#x27;, &#x27;Bruschetta&#x27;, &#x27;Garlic Bread&#x27;, &#x27;Caprese Salad&#x27; ]</span></span><br></pre></td></tr></table></figure>
<p>构造能处理任意参数的函数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> add = <span class="function"><span class="keyword">function</span> (<span class="params">...numbers</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> sum = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> number <span class="keyword">of</span> numbers) &#123;</span><br><span class="line">        sum += number;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">console</span>.log(sum);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">add(<span class="number">2</span>, <span class="number">4</span>); <span class="comment">//6</span></span><br><span class="line">add(<span class="number">2</span>, <span class="number">5</span>, <span class="number">8</span>, <span class="number">10</span>); <span class="comment">//25</span></span><br><span class="line">add(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">13</span>, <span class="number">17</span>); <span class="comment">//48</span></span><br></pre></td></tr></table></figure>
<p>另一个函数使用 <code>rest</code> 参数的例子：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">restaurant.orderPizza = <span class="function"><span class="keyword">function</span> (<span class="params">mainIngredient, ...otherIngredients</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(mainIngredient);</span><br><span class="line">    <span class="built_in">console</span>.log(otherIngredients);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">restaurant.orderPizza(<span class="string">&quot;mushrooms&quot;</span>, <span class="string">&quot;onion&quot;</span>, <span class="string">&quot;olives&quot;</span>, <span class="string">&quot;spinach&quot;</span>); <span class="comment">//[ &#x27;onion&#x27;, &#x27;olives&#x27;, &#x27;spinach&#x27; ]</span></span><br></pre></td></tr></table></figure>
<h3 id="逻辑短路与分配运算符">逻辑短路与分配运算符</h3>
<p><code>&amp;&amp;</code>，<code>||</code>，<code>??</code> 可以实现逻辑短路。</p>
<ul>
<li>
<p><code>||</code> 划分的语句返回第一个真值语句的值，如果都是假值，则返回最后一个。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="number">3</span> || <span class="string">&quot;vonbrank&quot;</span>); <span class="comment">//3</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="literal">false</span> || <span class="number">0</span>); <span class="comment">//0</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="literal">null</span> || <span class="literal">undefined</span>); <span class="comment">//undefiend</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="literal">undefined</span> || <span class="literal">null</span>); <span class="comment">//null</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">0</span> || <span class="literal">null</span> || <span class="literal">undefined</span> || <span class="string">&quot;&quot;</span> || <span class="string">&quot;hello&quot;</span> || <span class="number">23</span>);</span><br><span class="line"><span class="comment">// hello</span></span><br></pre></td></tr></table></figure>
<p>这种操作可以检测并初始化变量：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">restaurant.numGuests = <span class="number">20</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//方案1</span></span><br><span class="line"><span class="keyword">const</span> guests1 = restaurant.numGuests ? restaurant.numGuests : <span class="number">10</span>;</span><br><span class="line"><span class="built_in">console</span>.log(guests1); <span class="comment">//20</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//方案2</span></span><br><span class="line"><span class="keyword">const</span> guests2 = restaurant.numGuests || <span class="number">10</span>;</span><br><span class="line"><span class="built_in">console</span>.log(guests2); <span class="comment">//20</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//相比之下使用短路运算符更方便。</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>&amp;&amp;</code> 与 <code>||</code> 相反，其返回第一个为假值的语句的返回值，如果都是真值，则返回最后一个。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;vonbrank&quot;</span> &amp;&amp; <span class="literal">false</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">0</span> &amp;&amp; <span class="string">&quot;vonbrank&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">7</span> &amp;&amp; <span class="string">&quot;vonbrank&quot;</span>);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p><code>??</code> 与 <code>||</code> 几乎一样，但是它只会跳过 <code>null</code> 和 <code>undefined</code> ， <code>0</code> 、 <code>&quot;&quot;</code> 、 <code>false</code> 不受影响。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">restaurant.numGuests = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">const</span> guests2 = restaurant.numGuests ?? <span class="number">10</span>;</span><br><span class="line"><span class="built_in">console</span>.log(guests2); <span class="comment">//10</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="literal">undefined</span> ?? <span class="number">0</span> ?? <span class="string">&quot;hello&quot;</span>); <span class="comment">//0</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>短路运算符不仅仅会返回值，被其隔开的每一个语句在短路之前都将被执行。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (restaurant.orderPizza) &#123;</span><br><span class="line">    restaurant.orderPizza(<span class="string">&quot;mushrooms&quot;</span>, <span class="string">&quot;spinach&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">restaurant.orderPizza &amp;&amp; restaurant.orderPizza(<span class="string">&quot;mushrooms&quot;</span>, <span class="string">&quot;spinach&quot;</span>);</span><br></pre></td></tr></table></figure>
<p>上述 <code>restaurant.orderPizza</code> 为真值，所以 <code>&amp;&amp;</code> 右边的语句被继续执行，实现了 <code>if</code> 的功能，但需要注意的是，我们不提倡滥用短路运算符乃至放弃使用 <code>if</code> 语句，因为滥用会影响代码的可读性。</p>
<p>因此短路运算符的实质是：执行被运算符隔开的每一条语句，直至短路，并返回最后一条语句的返回值。其中， <code>||</code> 被真值短路，<code>&amp;&amp;</code> 被假值短路，<code>??</code> 被除了 <code>null</code> 、 <code>undefined</code> 外的值短路。</p>
<p>JavaScript ES2020 提供了全新的逻辑分配符： <code>||=</code>、<code>&amp;&amp;=</code>、<code>??=</code></p>
<p>可用于化简包含短路运算符的语句：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">restaurant1.numGuests = restaurant1.numGuests || <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line">restaurant1.numGuests ||= <span class="number">10</span>;</span><br><span class="line"><span class="comment">//等价于 restaurant1.numGuests = restaurant1.numGuests || 10;</span></span><br><span class="line"></span><br><span class="line">restaurant2.numGuests ||= <span class="number">10</span>;</span><br><span class="line"><span class="comment">//等价于 restaurant2.numGuests = restaurant2.numGuests || 10;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(restaurant1.numGuests); <span class="comment">//10</span></span><br><span class="line"><span class="built_in">console</span>.log(restaurant2.numGuests); <span class="comment">//10</span></span><br><span class="line"></span><br><span class="line">restaurant2.owner &amp;&amp;= <span class="string">&quot;&lt;ANONYMOUS&gt;&quot;</span>;</span><br><span class="line"><span class="comment">//等价于 restaurant2.owner = restaurant2.owner &amp;&amp; &quot;&lt;ANONYMOUS&gt;&quot;</span></span><br><span class="line"><span class="built_in">console</span>.log(restaurant2.owner);</span><br></pre></td></tr></table></figure>
<p>此处需要注意，分配符左侧需要是有效左值，即可被赋值的变量。</p>
<h3 id="高级循环">高级循环</h3>
<ul>
<li>
<p><code>for-of</code> 循环</p>
<p><code>for-of</code> 循环写法如下，可以免去自定义循环变量的麻烦：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> menu = [...restaurant.starterMenu, ...restaurant.mainMenu];</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> item <span class="keyword">of</span> menu) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(item);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Focaccia</span></span><br><span class="line"><span class="comment">// Bruschetta</span></span><br><span class="line"><span class="comment">// Garlic Bread</span></span><br><span class="line"><span class="comment">// Caprese Salad</span></span><br><span class="line"><span class="comment">// Pizza</span></span><br><span class="line"><span class="comment">// Pasta</span></span><br><span class="line"><span class="comment">// Risotto</span></span><br></pre></td></tr></table></figure>
<p><code>for-of</code> 依然可以使用索引：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> [i, item] <span class="keyword">of</span> menu.entries()) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;i + <span class="number">1</span>&#125;</span>. <span class="subst">$&#123;item&#125;</span>`</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//1. Focaccia</span></span><br><span class="line"><span class="comment">//2. Bruschetta</span></span><br><span class="line"><span class="comment">//3. Garlic Bread</span></span><br><span class="line"><span class="comment">//4. Caprese Salad</span></span><br><span class="line"><span class="comment">//5. Pizza</span></span><br><span class="line"><span class="comment">//6. Pasta</span></span><br><span class="line"><span class="comment">//7. Risotto</span></span><br></pre></td></tr></table></figure>
<p><code>for-of</code> 循环也适用于对象：</p>
<p><code>Object.keys()</code> 可以返回对象关键字的数组：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> day <span class="keyword">of</span> <span class="built_in">Object</span>.keys(openingHours)) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(day);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//Thu</span></span><br><span class="line"><span class="comment">//Fri</span></span><br><span class="line"><span class="comment">//Sat</span></span><br></pre></td></tr></table></figure>
<p><code>Object.values()</code> 可以返回对象值的数组。</p>
<p><code>Object.entries()</code> 返回对象 <code>[key, value]</code> 的数组。</p>
<p>一个灵活使用对象迭代器、解构赋值与 <code>for-of</code> 的例子：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> [key, &#123; open, close &#125;] <span class="keyword">of</span> <span class="built_in">Object</span>.entries(openingHours)) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`On <span class="subst">$&#123;key&#125;</span>, we open at <span class="subst">$&#123;open&#125;</span> and close at <span class="subst">$&#123;close&#125;</span>`</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//On Thu, we open at 12 and close at 22</span></span><br><span class="line"><span class="comment">//On Fri, we open at 11 and close at 23</span></span><br><span class="line"><span class="comment">//On Sat, we open at 0 and close at 24</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="增强型对象字面值与可选链">增强型对象字面值与可选链</h3>
<p>JavaScript 对象成员的名称是可计算的，只需要用 <code>[]</code> 包裹即可：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> weekdays = [<span class="string">&quot;Sun&quot;</span>, <span class="string">&quot;Mon&quot;</span>, <span class="string">&quot;Tue&quot;</span>, <span class="string">&quot;Wed&quot;</span>, <span class="string">&quot;Thu&quot;</span>, <span class="string">&quot;Fri&quot;</span>, <span class="string">&quot;Sat&quot;</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> openingHours = &#123;</span><br><span class="line">    [<span class="string">`<span class="subst">$&#123;weekdays[<span class="number">4</span>]&#125;</span>`</span>]: &#123;</span><br><span class="line">        open: <span class="number">12</span>,</span><br><span class="line">        close: <span class="number">22</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    Fri: &#123;</span><br><span class="line">        open: <span class="number">11</span>,</span><br><span class="line">        close: <span class="number">23</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    Sat: &#123;</span><br><span class="line">        open: <span class="number">0</span>, <span class="comment">// Open 24 hours</span></span><br><span class="line">        close: <span class="number">24</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">console</span>.log(openingHours);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">&#123;</span></span><br><span class="line"><span class="comment">  Thu: &#123; open: 12, close: 22 &#125;,</span></span><br><span class="line"><span class="comment">  Fri: &#123; open: 11, close: 23 &#125;,</span></span><br><span class="line"><span class="comment">  Sat: &#123; open: 0, close: 24 &#125;</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>实际项目中常常需要操作一个未知对象：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(restaurant.openingHours.mon.open);</span><br></pre></td></tr></table></figure>
<p>我们不确定 <code>restaurant.openingHours</code> 是否有 <code>mon</code> 这个成员，一旦没有，就会报异常。所以通常这么写：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (restaurant.openingHours.mon) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(restaurant.openingHours.mon.open);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>ES6 提供了可选链简化此类代码。</p>
<p>若不知道某个成员是否存在，可以在其后加一个 <code>?</code> ，若不存在则直接返回 <code>undefined</code> ，防止访问形如 <code>undefined.open</code> 导致异常。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(restaurant.openingHours.mon?.open); <span class="comment">//undefined</span></span><br></pre></td></tr></table></figure>
<p>可用来判断方法是否存在：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(restaurant.order1?.(<span class="number">0</span>, <span class="number">1</span>) ?? <span class="string">&quot;Method does not exist&quot;</span>); <span class="comment">//Method does not exist</span></span><br></pre></td></tr></table></figure>
<p>判断对象成员是否存在：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> users = [</span><br><span class="line">    &#123; <span class="attr">name</span>: <span class="string">&quot;vonbrank&quot;</span>, <span class="attr">job</span>: <span class="string">&quot;student&quot;</span> &#125;,</span><br><span class="line">    &#123; <span class="attr">name</span>: <span class="string">&quot;alice&quot;</span>, <span class="attr">job</span>: <span class="string">&quot;Engineer&quot;</span> &#125;,</span><br><span class="line">];</span><br><span class="line"><span class="built_in">console</span>.log(users[<span class="number">0</span>]?.name || <span class="string">&quot;user property does not exist&quot;</span>); <span class="comment">///vonbrank</span></span><br><span class="line"><span class="built_in">console</span>.log(users[<span class="number">2</span>]?.name || <span class="string">&quot;user property does not exist&quot;</span>); <span class="comment">//user property does not exist</span></span><br></pre></td></tr></table></figure>
<h3 id="Map-和-Set"><code>Map</code> 和 <code>Set</code></h3>
<p>和数学上的 <code>集合</code> 完全类似， JavaScript 中的 <code>Set</code> 是一种只允许任何元素出现一次的数据结构。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> orderSet = <span class="keyword">new</span> <span class="built_in">Set</span>([</span><br><span class="line">    <span class="string">&quot;Pizza&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Pasta&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Pizza&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Pizza&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Risotto&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Pasta&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Pizza&quot;</span>,</span><br><span class="line">]);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(orderSet); <span class="comment">//Set(3) &#123; &#x27;Pizza&#x27;, &#x27;Pasta&#x27;, &#x27;Risotto&#x27; &#125;</span></span><br><span class="line"><span class="built_in">console</span>.log(orderSet.size); <span class="comment">//3</span></span><br><span class="line"><span class="built_in">console</span>.log(orderSet.has(<span class="string">&quot;Pizza&quot;</span>)); <span class="comment">//true</span></span><br><span class="line"><span class="built_in">console</span>.log(orderSet.has(<span class="string">&quot;Bread&quot;</span>)); <span class="comment">//false</span></span><br><span class="line"></span><br><span class="line">orderSet.add(<span class="string">&quot;Garlic Bread&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(orderSet); <span class="comment">//Set(4) &#123; &#x27;Pizza&#x27;, &#x27;Pasta&#x27;, &#x27;Risotto&#x27;, &#x27;Garlic Bread&#x27; &#125;</span></span><br><span class="line">orderSet.delete(<span class="string">&quot;Risotto&quot;</span>);</span><br><span class="line"><span class="comment">// orderSet.clear();</span></span><br><span class="line"><span class="built_in">console</span>.log(orderSet); <span class="comment">//Set(3) &#123; &#x27;Pizza&#x27;, &#x27;Pasta&#x27;, &#x27;Garlic Bread&#x27; &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//Set 是可迭代对象，可使用 for-of 循环</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">const</span> order <span class="keyword">of</span> orderSet) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(order);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//Set 拆解字符串</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">new</span> <span class="built_in">Set</span>(<span class="string">&quot;hello, world!&quot;</span>));</span><br><span class="line"><span class="comment">//Set(10) &#123; &#x27;h&#x27;, &#x27;e&#x27;, &#x27;l&#x27;, &#x27;o&#x27;, &#x27;,&#x27;, &#x27; &#x27;, &#x27;w&#x27;, &#x27;r&#x27;, &#x27;d&#x27;, &#x27;!&#x27; &#125;</span></span><br></pre></td></tr></table></figure>
<p><code>Map</code> 可建立其两个元素的配对。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> restaurant3 = <span class="keyword">new</span> <span class="built_in">Map</span>();</span><br><span class="line"></span><br><span class="line">restaurant3.set(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;origus&quot;</span>);</span><br><span class="line">restaurant3.set(<span class="number">1</span>, <span class="string">&quot;Italy&quot;</span>);</span><br><span class="line">restaurant3.set(<span class="number">2</span>, <span class="string">&quot;Franch&quot;</span>);</span><br><span class="line">restaurant3</span><br><span class="line">    .set(<span class="string">&quot;categories&quot;</span>, [<span class="string">&quot;Italian&quot;</span>, <span class="string">&quot;Pizzeria&quot;</span>, <span class="string">&quot;Vegetarian&quot;</span>, <span class="string">&quot;Organic&quot;</span>])</span><br><span class="line">    .set(<span class="string">&quot;open&quot;</span>, <span class="string">&quot;11&quot;</span>)</span><br><span class="line">    .set(<span class="string">&quot;close&quot;</span>, <span class="string">&quot;23&quot;</span>)</span><br><span class="line">    .set(<span class="literal">true</span>, <span class="string">&quot;we are open&quot;</span>)</span><br><span class="line">    .set(<span class="literal">false</span>, <span class="string">&quot;we are closed&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(restaurant3);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Map(8) &#123;</span></span><br><span class="line"><span class="comment">  &#x27;name&#x27; =&gt; &#x27;origus&#x27;,</span></span><br><span class="line"><span class="comment">  1 =&gt; &#x27;Italy&#x27;,</span></span><br><span class="line"><span class="comment">  2 =&gt; &#x27;Franch&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;categories&#x27; =&gt; [ &#x27;Italian&#x27;, &#x27;Pizzeria&#x27;, &#x27;Vegetarian&#x27;, &#x27;Organic&#x27; ],</span></span><br><span class="line"><span class="comment">  &#x27;open&#x27; =&gt; &#x27;11&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;close&#x27; =&gt; &#x27;23&#x27;,</span></span><br><span class="line"><span class="comment">  true =&gt; &#x27;we are open&#x27;,</span></span><br><span class="line"><span class="comment">  false =&gt; &#x27;we are closed&#x27;</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(restaurant3.get(<span class="string">&quot;name&quot;</span>)); <span class="comment">//origus</span></span><br><span class="line">restaurant3.delete(<span class="number">2</span>);</span><br><span class="line"><span class="built_in">console</span>.log(restaurant3);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log([...restaurant3.entries()]);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">[</span></span><br><span class="line"><span class="comment">  [ &#x27;name&#x27;, &#x27;origus&#x27; ],</span></span><br><span class="line"><span class="comment">  [ 1, &#x27;Italy&#x27; ],</span></span><br><span class="line"><span class="comment">  [ &#x27;categories&#x27;, [ &#x27;Italian&#x27;, &#x27;Pizzeria&#x27;, &#x27;Vegetarian&#x27;, &#x27;Organic&#x27; ] ],</span></span><br><span class="line"><span class="comment">  [ &#x27;open&#x27;, &#x27;11&#x27; ],</span></span><br><span class="line"><span class="comment">  [ &#x27;close&#x27;, &#x27;23&#x27; ],</span></span><br><span class="line"><span class="comment">  [ true, &#x27;we are open&#x27; ],</span></span><br><span class="line"><span class="comment">  [ false, &#x27;we are closed&#x27; ]</span></span><br><span class="line"><span class="comment">]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(restaurant3.has(<span class="string">&quot;categories&quot;</span>)); <span class="comment">//true</span></span><br><span class="line"><span class="built_in">console</span>.log(restaurant3.size); <span class="comment">//7</span></span><br></pre></td></tr></table></figure>
<h3 id="字符串操作">字符串操作</h3>
<p>JavaScript 提供许多操作字符串的方法。</p>
<ul>
<li>
<p>索引搜索与切片</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> airline = <span class="string">&quot;TAP Air Portugal&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> plane = <span class="string">&quot;A320&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(plane[<span class="number">0</span>]); <span class="comment">//A</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;B747&quot;</span>[<span class="number">0</span>]); <span class="comment">//B</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//搜索字符串第一个索引位置，找不到返回 -1</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.indexOf(<span class="string">&quot;Portugal&quot;</span>)); <span class="comment">//10</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//搜索字符串最后一个索引位置</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.lastIndexOf(<span class="string">&quot;r&quot;</span>)); <span class="comment">//8</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//.slice 用于字符串切片</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.slice(<span class="number">5</span>)); <span class="comment">//ir Portugal</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.slice(<span class="number">4</span>, <span class="number">7</span>)); <span class="comment">//Air</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//字符串切片结合索引位置实现切片第一个单词</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.slice(<span class="number">0</span>, airline.indexOf(<span class="string">&quot; &quot;</span>))); <span class="comment">//TAP</span></span><br><span class="line"><span class="comment">//切片最后一个单词</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.slice(airline.lastIndexOf(<span class="string">&quot; &quot;</span>) + <span class="number">1</span>)); <span class="comment">//Portugal</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//负数切片表示倒数位置</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.slice(-<span class="number">2</span>)); <span class="comment">//al</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.slice(<span class="number">1</span>, -<span class="number">1</span>)); <span class="comment">//AP Air Portuga</span></span><br></pre></td></tr></table></figure>
<p>实例：判断座位是不是在中间</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> checkMiddleSeat = <span class="function"><span class="keyword">function</span> (<span class="params">seat</span>) </span>&#123;</span><br><span class="line">    <span class="comment">//B and E are middle seats</span></span><br><span class="line">    <span class="keyword">const</span> s = seat.slice(-<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span> (s === <span class="string">&quot;B&quot;</span> || s === <span class="string">&quot;E&quot;</span>) &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;You get a middle seat.&quot;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;You got lucky.&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">checkMiddleSeat(<span class="string">&quot;11B&quot;</span>); <span class="comment">//You get a middle seat.</span></span><br><span class="line">checkMiddleSeat(<span class="string">&quot;23C&quot;</span>); <span class="comment">//You got lucky.</span></span><br><span class="line">checkMiddleSeat(<span class="string">&quot;3E&quot;</span>); <span class="comment">//You get a middle seat.</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p>大小写转换、去除空白字符、替换、前后缀判断</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> airline = <span class="string">&quot;TAP Air Portugal&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//大小写转换</span></span><br><span class="line"><span class="built_in">console</span>.log(airline.toUpperCase());</span><br><span class="line"><span class="built_in">console</span>.log(airline.toLowerCase());</span><br><span class="line"></span><br><span class="line"><span class="comment">//字符串格式化转为首字母大写</span></span><br><span class="line"><span class="keyword">const</span> passenger = <span class="string">&quot;vONBrNk&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> passengerLower = passenger.toLowerCase();</span><br><span class="line"><span class="keyword">const</span> passengerCorrect =</span><br><span class="line">    passenger[<span class="number">0</span>].toUpperCase() + passengerLower.slice(<span class="number">1</span>);</span><br><span class="line"><span class="built_in">console</span>.log(passengerCorrect);</span><br><span class="line"></span><br><span class="line"><span class="comment">//格式化邮箱，去除末尾回车字符</span></span><br><span class="line"><span class="keyword">const</span> email = <span class="string">&quot;hello@vonbrank.com&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> emailLogin = <span class="string">&quot;HelLo@vOnBRnk.CoM \n&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> emailLower = emailLogin.toLowerCase();</span><br><span class="line"><span class="keyword">const</span> emailTrimmed = emailLower.trim();</span><br><span class="line"><span class="built_in">console</span>.log(emailTrimmed);</span><br><span class="line"></span><br><span class="line"><span class="comment">//字符串方法均返回新字符串引用，因此可以连续调用</span></span><br><span class="line"><span class="keyword">const</span> emailNormalized = emailLogin.toLowerCase().trim();</span><br><span class="line"><span class="built_in">console</span>.log(emailNormalized);</span><br><span class="line"><span class="built_in">console</span>.log(emailTrimmed === emailNormalized);</span><br><span class="line"></span><br><span class="line"><span class="comment">// .replace(d, t) 可以把第一个 d 替换为 t</span></span><br><span class="line"><span class="keyword">const</span> priceGB = <span class="string">&quot;288,97￡&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> priceUS = priceGB.replace(<span class="string">&quot;￡&quot;</span>, <span class="string">&quot;$&quot;</span>).replace(<span class="string">&quot;,&quot;</span>, <span class="string">&quot;.&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(priceUS);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> announcements =</span><br><span class="line">    <span class="string">&quot;All passengers come to boarding door 23. Boarding door 23!&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(announcements.replace(<span class="string">&quot;door&quot;</span>, <span class="string">&quot;gate&quot;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">//ReplaceAll 是 ES2021 新特性</span></span><br><span class="line"><span class="built_in">console</span>.log(announcements.replaceAll(<span class="string">&quot;door&quot;</span>, <span class="string">&quot;gate&quot;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用正则表达式可以实现仅用 replace 方法替换所有字符串</span></span><br><span class="line"><span class="built_in">console</span>.log(announcements.replace(<span class="regexp">/door/g</span>, <span class="string">&quot;gate&quot;</span>));</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> plane = <span class="string">&quot;Airbus A320neo&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(plane.includes(<span class="string">&quot;A320&quot;</span>)); <span class="comment">//true</span></span><br><span class="line"><span class="built_in">console</span>.log(plane.includes(<span class="string">&quot;Boeing&quot;</span>)); <span class="comment">//false</span></span><br><span class="line"><span class="comment">// console.log(plane.startsWith(&quot;A3&quot;)); //true</span></span><br><span class="line"><span class="built_in">console</span>.log(plane.startsWith(<span class="string">&quot;Air&quot;</span>)); <span class="comment">//false</span></span><br></pre></td></tr></table></figure>
<p>一个例子，实现违禁品判断：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (plane.startsWith(<span class="string">&quot;Airbus&quot;</span>) &amp;&amp; plane.endsWith(<span class="string">&quot;neo&quot;</span>)) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;Part of the new Airbus family&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> checkBaggage = <span class="function"><span class="keyword">function</span> (<span class="params">items</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> baggage = items.toLowerCase();</span><br><span class="line">    <span class="keyword">if</span> (baggage.includes(<span class="string">&quot;knife&quot;</span>) || baggage.includes(<span class="string">&quot;gun&quot;</span>)) &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;You are not allowed on board.&quot;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="built_in">console</span>.log(<span class="string">&quot;Welcome aboard.&quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">checkBaggage(<span class="string">&quot;I have a laptop, some Food and a pocket Knife.&quot;</span>);</span><br><span class="line">checkBaggage(<span class="string">&quot;Socks and camera&quot;</span>);</span><br><span class="line">checkBaggage(<span class="string">&quot;Got some snacks and a gun for protection&quot;</span>);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>字符串分割与合并、追加与扩充、倍增</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//split 用来分割字符串，传入需要分割的字符</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;a+very+nice+string&quot;</span>.split(<span class="string">&quot;+&quot;</span>));</span><br><span class="line"><span class="comment">//[ &#x27;a&#x27;, &#x27;very&#x27;, &#x27;nice&#x27;, &#x27;string&#x27; ]</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;von brank&quot;</span>.split(<span class="string">&quot; &quot;</span>));</span><br><span class="line"><span class="comment">//[ &#x27;von&#x27;, &#x27;brank&#x27; ]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> [firstName, lastName] = <span class="string">&quot;von brank&quot;</span>.split(<span class="string">&quot; &quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(firstName, lastName);</span><br><span class="line"></span><br><span class="line"><span class="comment">//join 可将数组里的字符串用传入字符连接</span></span><br><span class="line"><span class="keyword">const</span> newName = [<span class="string">&quot;Mr.&quot;</span>, firstName, lastName.toUpperCase()].join(<span class="string">&quot; &quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(newName); <span class="comment">//  Mr. von BRANK</span></span><br></pre></td></tr></table></figure>
<p>一个将首字母转大写的例子</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> capitalizeName = <span class="function"><span class="keyword">function</span> (<span class="params">name</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> names = name.split(<span class="string">&quot; &quot;</span>);</span><br><span class="line">    <span class="keyword">const</span> capitalizedName = [];</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> n <span class="keyword">of</span> names) &#123;</span><br><span class="line">        <span class="comment">// n[0]  &amp;&amp; capitalizedName.push(n[0].toUpperCase() + n.slice(1));</span></span><br><span class="line">        n[<span class="number">0</span>] &amp;&amp; capitalizedName.push(n.replace(n[<span class="number">0</span>], n[<span class="number">0</span>].toUpperCase()));</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> capitalizedName.join(<span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> passenger = <span class="string">&quot;jassica ann smith davis&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(capitalizeName(passenger));</span><br><span class="line"><span class="comment">//Jassica Ann Smith Davis</span></span><br></pre></td></tr></table></figure>
<p><code>padStart</code> 与 <code>padEnd</code> 可以实现在字符串前后或填充字符至指定长度：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> message = <span class="string">&quot;Go to gate 23&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(message.padStart(<span class="number">25</span>, <span class="string">&quot;+&quot;</span>));</span><br><span class="line"><span class="comment">//++++++++++++Go to gate 23</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;vonbrank&quot;</span>.padEnd(<span class="number">23</span>, <span class="string">&quot;+&quot;</span>));</span><br><span class="line"><span class="comment">//vonbrank+++++++++++++++</span></span><br></pre></td></tr></table></figure>
<p>一个创建掩码的例子：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> maskCreditCard = <span class="function"><span class="keyword">function</span> (<span class="params">number</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> str = <span class="built_in">String</span>(number);</span><br><span class="line">    <span class="keyword">const</span> last = str.slice(-<span class="number">4</span>);</span><br><span class="line">    <span class="keyword">return</span> last.padStart(str.length, <span class="string">&quot;*&quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(maskCreditCard(<span class="number">14285731415926</span>));</span><br><span class="line"><span class="comment">//**********5926</span></span><br></pre></td></tr></table></figure>
<p><code>string.repeat(n)</code> 可以实现将 <code>string</code> 重复 <code>n</code> 次</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> message2 = <span class="string">&quot;Bad weather... All departures delayed...\n&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(message2.repeat(<span class="number">5</span>));</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Bad weather... All departures delayed...</span></span><br><span class="line"><span class="comment">Bad weather... All departures delayed...</span></span><br><span class="line"><span class="comment">Bad weather... All departures delayed...</span></span><br><span class="line"><span class="comment">Bad weather... All departures delayed...</span></span><br><span class="line"><span class="comment">Bad weather... All departures delayed...</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> planesInLine = <span class="function"><span class="keyword">function</span> (<span class="params">n</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`There are <span class="subst">$&#123;n&#125;</span> planes in line. <span class="subst">$&#123;<span class="string">&quot;✈️&quot;</span>.repeat(n)&#125;</span>`</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">planesInLine(<span class="number">5</span>); <span class="comment">//There are 5 planes in line. ✈️✈️✈️✈️✈️</span></span><br><span class="line">planesInLine(<span class="number">3</span>); <span class="comment">//There are 3 planes in line. ✈️✈️✈️</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="深入理解-JavaScript-函数">深入理解 JavaScript 函数</h2>
<h3 id="默认参数与引用传递">默认参数与引用传递</h3>
<p>ES6 的新特性之一就是允许函数设置默认参数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> bookings = [];</span><br><span class="line"><span class="keyword">const</span> createBooking = <span class="function"><span class="keyword">function</span> (<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params">    flightNum,</span></span></span><br><span class="line"><span class="function"><span class="params">    numPassengers = <span class="number">1</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">    price = <span class="number">100</span> * numPassengers</span></span></span><br><span class="line"><span class="function"><span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">//ES5 way</span></span><br><span class="line">    <span class="comment">// numPassengers ||= 1;</span></span><br><span class="line">    <span class="comment">// price ||= 100;</span></span><br><span class="line">    <span class="keyword">const</span> booking = &#123;</span><br><span class="line">        flightNum,</span><br><span class="line">        numPassengers,</span><br><span class="line">        price,</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="built_in">console</span>.log(booking);</span><br><span class="line">    bookings.push(booking);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">createBooking(<span class="string">&quot;CZ6369&quot;</span>);</span><br><span class="line">createBooking(<span class="string">&quot;CZ6371&quot;</span>, <span class="literal">undefined</span>, <span class="number">200</span>);</span><br><span class="line">createBooking(<span class="string">&quot;CZ6371&quot;</span>, <span class="number">10</span>, <span class="number">399</span>);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">&#123; flightNum: &#x27;CZ6369&#x27;, numPassengers: 1, price: 100 &#125;</span></span><br><span class="line"><span class="comment">&#123; flightNum: &#x27;CZ6371&#x27;, numPassengers: 1, price: 200 &#125;</span></span><br><span class="line"><span class="comment">&#123; flightNum: &#x27;CZ6371&#x27;, numPassengers: 10, price: 399 &#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>函数参数如果是基本类型，则传入值，对象传入引用，因此在函数内修改对象将使得原对象被修改：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> flight = <span class="string">&quot;CZ6371&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> vonbrank = &#123;</span><br><span class="line">    name: <span class="string">&quot;Von Brank&quot;</span>,</span><br><span class="line">    passport: <span class="number">1234567</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> checkIn = <span class="function"><span class="keyword">function</span> (<span class="params">flightNum, passenger</span>) </span>&#123;</span><br><span class="line">    flightNum = <span class="string">&quot;CZ6666&quot;</span>;</span><br><span class="line">    passenger.name = <span class="string">&quot;Mr.&quot;</span> + passenger.name;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (passenger.passport === <span class="number">1234567</span>) &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;check in&quot;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="built_in">console</span>.log(<span class="string">&quot;wrong passport&quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">checkIn(flight, vonbrank);</span><br><span class="line"><span class="built_in">console</span>.log(flight, vonbrank);</span><br><span class="line"><span class="comment">// CZ6371 &#123; name: &#x27;Mr.Von Brank&#x27;, passport: 1234567 &#125;</span></span><br></pre></td></tr></table></figure>
<h3 id="高阶函数与回调函数">高阶函数与回调函数</h3>
<p>JavaScript 的重要特性之一就是所谓的 Firt-Class Function ，即函数与普通变量同等看待，有 First-Class Function 便有 High Order Function</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> oneWord = <span class="function"><span class="keyword">function</span> (<span class="params">str</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> str.replace(<span class="regexp">/ /g</span>, <span class="string">&quot;&quot;</span>).toLowerCase();</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> upperFirstWord = <span class="function"><span class="keyword">function</span> (<span class="params">str</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> [first, ...other] = str.split(<span class="string">&quot; &quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> [first.toUpperCase(), ...other].join(<span class="string">&quot; &quot;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> transformer = <span class="function"><span class="keyword">function</span> (<span class="params">str, fn</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`Original string: <span class="subst">$&#123;str&#125;</span>`</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`Transformed string: <span class="subst">$&#123;fn(str)&#125;</span>`</span>);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`Transformed by: <span class="subst">$&#123;fn.name&#125;</span>`</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">transformer(<span class="string">&quot;JavaScript is the best language!&quot;</span>, upperFirstWord);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Original string: JavaScript is the best language!</span></span><br><span class="line"><span class="comment">Transformed string: JAVASCRIPT is the best language!</span></span><br><span class="line"><span class="comment">Transformed by: upperFirstWord</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line">transformer(<span class="string">&quot;JavaScript is the best language!&quot;</span>, oneWord);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Original string: JavaScript is the best language!</span></span><br><span class="line"><span class="comment">Transformed string: javascriptisthebestlanguage!</span></span><br><span class="line"><span class="comment">Transformed by: oneWord</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>这个例子展示了 <code>transformer</code> 接收一个 <code>string</code> 和一个 <code>fn</code> ，<code>transformer</code> 不在乎 <code>fn</code> 将以怎样的方式处理 <code>string</code> ，只需要 <code>fn</code> 接收 <code>str</code> 处理并返回一个值即可， <code>transformer</code> 内部将调用 <code>fn</code> 传入 <code>string</code> 并执行。</p>
<p>这里的 <code>fn</code> 便是所谓的回调函数（call back function） ，意思是把函数当作值传入，稍后再调用。</p>
<p>JavaScript 总是以回调的形式执行函数；<code>forEach</code>、<code>addEventListener</code> 也是接受回调函数的高阶函数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//JavaScript used callback all the time</span></span><br><span class="line"><span class="keyword">const</span> high5 = <span class="function"><span class="keyword">function</span> (<span class="params">item</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;Hooray!&quot;</span>);</span><br><span class="line">    <span class="built_in">console</span>.log(item);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.body.addEventListener(<span class="string">&quot;click&quot;</span>, high5);</span><br><span class="line"></span><br><span class="line">[<span class="string">&quot;VonBrank&quot;</span>, <span class="string">&quot;Alice&quot;</span>, <span class="string">&quot;Bob&quot;</span>, <span class="string">&quot;Cathy&quot;</span>].forEach(high5);</span><br></pre></td></tr></table></figure>
<h3 id="call、apply-与-bind-方法"><code>call</code>、<code>apply</code> 与 <code>bind</code> 方法</h3>
<p>通常，对对象的成员函数，我们可以用 <code>.</code> 运算符来直接执行：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> nanHang = &#123;</span><br><span class="line">    airline: <span class="string">&quot;nanHang&quot;</span>,</span><br><span class="line">    iataCode: <span class="string">&quot;CZ&quot;</span>,</span><br><span class="line">    bookings: [],</span><br><span class="line">    book: <span class="function"><span class="keyword">function</span> (<span class="params">flightNum, passengerName</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(</span><br><span class="line">            <span class="string">`<span class="subst">$&#123;passengerName&#125;</span> booked a seat on <span class="subst">$&#123;<span class="built_in">this</span>.airline&#125;</span> flight <span class="subst">$&#123;<span class="built_in">this</span>.iataCode&#125;</span><span class="subst">$&#123;flightNum&#125;</span>.`</span></span><br><span class="line">        );</span><br><span class="line">        <span class="built_in">this</span>.bookings.push(&#123;</span><br><span class="line">            flight: <span class="string">`<span class="subst">$&#123;<span class="built_in">this</span>.iataCode&#125;</span><span class="subst">$&#123;flightNum&#125;</span>`</span>,</span><br><span class="line">            name: passengerName,</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">nanHang.book(<span class="string">&quot;6371&quot;</span>, <span class="string">&quot;VonBrank&quot;</span>);</span><br><span class="line">nanHang.book(<span class="string">&quot;6317&quot;</span>, <span class="string">&quot;Smith&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(nanHang);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">VonBrank booked a seat on nanHang flight CZ6371.</span></span><br><span class="line"><span class="comment">Smith booked a seat on nanHang flight CZ6317.</span></span><br><span class="line"><span class="comment">&#123;</span></span><br><span class="line"><span class="comment">  airline: &#x27;nanHang&#x27;,</span></span><br><span class="line"><span class="comment">  iataCode: &#x27;CZ&#x27;,</span></span><br><span class="line"><span class="comment">  bookings: [</span></span><br><span class="line"><span class="comment">    &#123; flight: &#x27;CZ6371&#x27;, name: &#x27;VonBrank&#x27; &#125;,</span></span><br><span class="line"><span class="comment">    &#123; flight: &#x27;CZ6317&#x27;, name: &#x27;Smith&#x27; &#125;</span></span><br><span class="line"><span class="comment">  ],</span></span><br><span class="line"><span class="comment">  book: [Function: book]</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p>前文提到过，函数执行上下文中的 <code>this</code> 在不同调用条件下可能是不一样的。</p>
<p>如果我们想要把方法保存到另外的变量里，单独执行将导致 <code>this</code> 变成 <code>defined</code>，除了手动传入 <code>this</code> 参数，我们没有其他方法指定 <code>this</code>。</p>
<p>因此 JavaScript 提供了 <code>call</code>，<code>apply</code>和<code>bind</code> 三种方法便于开发者手动指定 <code>this</code> 变量的值。</p>
<p><code>call</code> 方法的第一个参数指定的的是函数执行时的 <code>this</code> 变量，之后依照调用函数的写法用逗号隔开所有传入的参数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> chuanHang = &#123;</span><br><span class="line">    airline: <span class="string">&quot;chuangHang&quot;</span>,</span><br><span class="line">    iataCode: <span class="string">&quot;3U&quot;</span>,</span><br><span class="line">    bookings: [],</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> book = nanHang.book;</span><br><span class="line"></span><br><span class="line">book.call(chuanHang, <span class="string">&quot;3456&quot;</span>, <span class="string">&quot;Steven&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(chuanHang);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Steven booked a seat on chuangHang flight 3U3456.</span></span><br><span class="line"><span class="comment">&#123;</span></span><br><span class="line"><span class="comment">  airline: &#x27;chuangHang&#x27;,</span></span><br><span class="line"><span class="comment">  iataCode: &#x27;3U&#x27;,</span></span><br><span class="line"><span class="comment">  bookings: [ &#123; flight: &#x27;3U3456&#x27;, name: &#x27;Steven&#x27; &#125; ]</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p><code>apply</code> 方法与 <code>call</code> 略有不同，对于函数原本接收的参数，需要以数组的形式传入：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> shenHang = &#123;</span><br><span class="line">    airline: <span class="string">&quot;Shenzhen Airline&quot;</span>,</span><br><span class="line">    iataCode: <span class="string">&quot;ZH&quot;</span>,</span><br><span class="line">    bookings: [],</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">book.call(shenHang, <span class="number">538</span>, <span class="string">&quot;Alice&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(shenHang);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> flightData = [<span class="number">583</span>, <span class="string">&quot;Cooper&quot;</span>];</span><br><span class="line">book.apply(shenHang, flightData);</span><br><span class="line"><span class="built_in">console</span>.log(shenHang);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">Alice booked a seat on Shenzhen Airline flight ZH538.</span></span><br><span class="line"><span class="comment">Cooper booked a seat on Shenzhen Airline flight ZH583.</span></span><br><span class="line"><span class="comment">&#123;</span></span><br><span class="line"><span class="comment">  airline: &#x27;Shenzhen Airline&#x27;,</span></span><br><span class="line"><span class="comment">  iataCode: &#x27;ZH&#x27;,</span></span><br><span class="line"><span class="comment">  bookings: [</span></span><br><span class="line"><span class="comment">    &#123; flight: &#x27;ZH538&#x27;, name: &#x27;Alice&#x27; &#125;,</span></span><br><span class="line"><span class="comment">    &#123; flight: &#x27;ZH583&#x27;, name: &#x27;Cooper&#x27; &#125;</span></span><br><span class="line"><span class="comment">  ]</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p><code>bind</code> 将 <code>this</code> 等参数的绑定与函数的执行分开：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> book3U = book.bind(chuanHang);</span><br><span class="line">book3U(<span class="number">1234</span>, <span class="string">&quot;Bob&quot;</span>); <span class="comment">//Bob booked a seat on chuangHang flight 3U1234.</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> bookCZ6371 = book.bind(nanHang, <span class="number">6371</span>);</span><br><span class="line">bookCZ6371(<span class="string">&quot;Cathy&quot;</span>); <span class="comment">//Cathy booked a seat on nanHang flight CZ6371.</span></span><br></pre></td></tr></table></figure>
<p>本例中 <code>const book3U = book.bind(chuanHang);</code> 将 <code>book3U</code> 的 <code>this</code> 变量永久钦定为 <code>chuanHang</code> 之后单独执行 <code>book3U</code> 时就像直接执行 <code>chuanHang.book</code> 一样； <code>const bookCZ6371 = book.bind(nanHang, 6371);</code> 则不仅绑定了 <code>this</code> 参数，还绑定了 <code>flightNum</code> 参数，之后 <code>bookCZ6371(&quot;Cathy&quot;)</code> 相当于原本执行 <code>nanHang.book(6371, &quot;Cathy&quot;);</code>。</p>
<p><code>bind</code> 还可以用在 <code>addEventListener</code> 中传入的回调函数是某个对象的方法，通过 <code>bind</code> 指定方法的 <code>this</code> 来防止出错。</p>
<h3 id="自执行匿名函数与闭包">自执行匿名函数与闭包</h3>
<p>想要创建一个独立的作用域，执行某些代码块，是编程中常见的需求， ES5 前常使用 Immediately Invoke Function Expression (IIFE) 实现：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">(functino () &#123;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`This function executes only once.`</span>);</span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure>
<p>现代 JavaScript 的做法是使用 <code>let</code> 和 <code>const</code> 变量将作用域限制在块级，然后使用单一的大括号创建代码块实现：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`This function executes only once.`</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>闭包（closure）是 JavaScript 中最容易让初学者感到困惑的东西。</p>
<p>先看一个例子：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> greet = <span class="function"><span class="keyword">function</span> (<span class="params">greeting</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">name</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;greeting&#125;</span> <span class="subst">$&#123;name&#125;</span>!`</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> greeterHey = greet(<span class="string">&quot;Hey&quot;</span>);</span><br><span class="line">greeterHey(<span class="string">&quot;Jonas&quot;</span>); <span class="comment">//Hey Jonas</span></span><br><span class="line">greeterHey(<span class="string">&quot;Von Brank&quot;</span>); <span class="comment">//Hey Von Brank</span></span><br><span class="line"></span><br><span class="line">greet(<span class="string">&quot;Hello&quot;</span>)(<span class="string">&quot;Alice&quot;</span>); <span class="comment">//Hello Alice</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> greetArrow = <span class="function">(<span class="params">greeting</span>) =&gt;</span> <span class="function">(<span class="params">name</span>) =&gt;</span> <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;greeting&#125;</span> <span class="subst">$&#123;name&#125;</span>!`</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> greeterArrowHey = greetArrow(<span class="string">&quot;Hey&quot;</span>);</span><br><span class="line">greeterArrowHey(<span class="string">&quot;Jonas&quot;</span>);</span><br></pre></td></tr></table></figure>
<p><code>greeting</code> 接收一个参数，返回的却是一个函数；本例中 <code>greeterHey</code> 就是一个从 <code>greet</code> 返回的函数，既然它是函数，就是可执行的。</p>
<p>问题在于， 执行 <code>greeterHey</code> 时需要访问 <code>greet</code> 函数中的 <code>greeting</code> 变量，而 <code>greet</code> 函数的上下文在此时早已结束，被弹出调用栈了，那这里的 <code>greeting</code> 是哪来的？ What the hell is it?</p>
<p>实现这一切的便是 JavaScript 的闭包机制！闭包的原理解释如图所示：</p>
<p><img src= "" data-lazy-src="https://s2.loli.net/2022/01/22/7fBAHnpctKyQ8i3.jpg" alt="note-javascript-closure"></p>
<p>如果函数返回的是另外一个函数，那么返回的函数会有一个成员变量，名为 <code>closure</code> ，里面包含了创建这个函数位置所处作用域内的所有变量的引用，当携带闭包的函数被执行时，若任何不在其作用域内的变量被访问，JavaScript 引擎都会先去闭包里搜索该变量，若找不到才接着到作用域链里搜索。</p>
<p>嵌套的箭头函数也是闭包：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> greetArrow = <span class="function">(<span class="params">greeting</span>) =&gt;</span> <span class="function">(<span class="params">name</span>) =&gt;</span> <span class="built_in">console</span>.log(<span class="string">`<span class="subst">$&#123;greeting&#125;</span> <span class="subst">$&#123;name&#125;</span>!`</span>);</span><br></pre></td></tr></table></figure>
<h2 id="数组的使用">数组的使用</h2>
<h3 id="数组基础方法">数组基础方法</h3>
<p><code>slice</code> 与 <code>splice</code> 用于数组切片，与字符串切片类似，不同之处在于， <code>splice</code> 将直接修改原数组，而 <code>slice</code> 不会：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>, <span class="string">&quot;e&quot;</span>, <span class="string">&quot;f&quot;</span>, <span class="string">&quot;g&quot;</span>];</span><br><span class="line"><span class="built_in">console</span>.log(arr.slice(<span class="number">2</span>, <span class="number">4</span>)); <span class="comment">//[ &#x27;c&#x27;, &#x27;d&#x27; ]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.slice(<span class="number">3</span>)); <span class="comment">//[ &#x27;d&#x27;, &#x27;e&#x27;, &#x27;f&#x27;, &#x27;g&#x27; ]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.slice(-<span class="number">1</span>)); <span class="comment">//[ &#x27;g&#x27; ]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.slice(<span class="number">1</span>, -<span class="number">2</span>)); <span class="comment">//[ &#x27;b&#x27;, &#x27;c&#x27;, &#x27;d&#x27;, &#x27;e&#x27; ]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.slice());</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">[</span></span><br><span class="line"><span class="comment">  &#x27;a&#x27;, &#x27;b&#x27;, &#x27;c&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;d&#x27;, &#x27;e&#x27;, &#x27;f&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;g&#x27;</span></span><br><span class="line"><span class="comment">]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line">arr = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>, <span class="string">&quot;e&quot;</span>, <span class="string">&quot;f&quot;</span>, <span class="string">&quot;g&quot;</span>];</span><br><span class="line"><span class="built_in">console</span>.log(arr.splice(<span class="number">2</span>)); <span class="comment">// [&quot;c&quot;, &quot;d&quot;, &quot;e&quot;, &quot;f&quot;, &quot;g&quot;]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr); <span class="comment">// [&quot;a&quot;, &quot;b&quot;]</span></span><br><span class="line"><span class="comment">//splice 会移除元素中中使用 splice 切片的部分</span></span><br></pre></td></tr></table></figure>
<p><code>reverse</code> 用于数组翻转，会直接修改原数组</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>, <span class="string">&quot;e&quot;</span>, <span class="string">&quot;f&quot;</span>, <span class="string">&quot;g&quot;</span>];</span><br><span class="line"><span class="keyword">const</span> arr2 = [<span class="string">&quot;h&quot;</span>, <span class="string">&quot;i&quot;</span>, <span class="string">&quot;j&quot;</span>, <span class="string">&quot;k&quot;</span>, <span class="string">&quot;l&quot;</span>];</span><br><span class="line"><span class="built_in">console</span>.log(arr2.reverse()); <span class="comment">//[ &#x27;l&#x27;, &#x27;k&#x27;, &#x27;j&#x27;, &#x27;i&#x27;, &#x27;h&#x27; ]</span></span><br><span class="line"><span class="built_in">console</span>.log(arr2); <span class="comment">//[ &#x27;l&#x27;, &#x27;k&#x27;, &#x27;j&#x27;, &#x27;i&#x27;, &#x27;h&#x27; ]</span></span><br></pre></td></tr></table></figure>
<p><code>concat</code> 用于拼接数组， <code>a.concat(b)</code> 表示将 <code>b</code> 拼接在 <code>a</code> 后面</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>, <span class="string">&quot;e&quot;</span>, <span class="string">&quot;f&quot;</span>, <span class="string">&quot;g&quot;</span>];</span><br><span class="line"><span class="keyword">const</span> arr2 = [<span class="string">&quot;h&quot;</span>, <span class="string">&quot;i&quot;</span>, <span class="string">&quot;j&quot;</span>, <span class="string">&quot;k&quot;</span>, <span class="string">&quot;l&quot;</span>];</span><br><span class="line"><span class="keyword">const</span> letters = arr.concat(arr2);</span><br><span class="line"><span class="built_in">console</span>.log(letters);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">[</span></span><br><span class="line"><span class="comment">  &#x27;a&#x27;, &#x27;b&#x27;, &#x27;c&#x27;, &#x27;d&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;e&#x27;, &#x27;f&#x27;, &#x27;g&#x27;, &#x27;h&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;i&#x27;, &#x27;j&#x27;, &#x27;k&#x27;, &#x27;l&#x27;</span></span><br><span class="line"><span class="comment">]</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="built_in">console</span>.log([...arr, ...arr2]);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">[</span></span><br><span class="line"><span class="comment">  &#x27;a&#x27;, &#x27;b&#x27;, &#x27;c&#x27;, &#x27;d&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;e&#x27;, &#x27;f&#x27;, &#x27;g&#x27;, &#x27;h&#x27;,</span></span><br><span class="line"><span class="comment">  &#x27;i&#x27;, &#x27;j&#x27;, &#x27;k&#x27;, &#x27;l&#x27;</span></span><br><span class="line"><span class="comment">]</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>
<p><code>join</code> 可以用指定符号连接数组中所有元素，并连接成字符串：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>, <span class="string">&quot;e&quot;</span>, <span class="string">&quot;f&quot;</span>, <span class="string">&quot;g&quot;</span>];</span><br><span class="line"><span class="built_in">console</span>.log(arr.join(<span class="string">&quot;-&quot;</span>)); <span class="comment">//a-b-c-d-e-f-g</span></span><br></pre></td></tr></table></figure>
<p>全新的 <code>.at()</code> 函数可以用于取代数组下标， <code>arr.at(i)</code> 返回第 <code>i</code> 个元素：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">23</span>, <span class="number">11</span>, <span class="number">64</span>];</span><br><span class="line"><span class="built_in">console</span>.log(arr[<span class="number">0</span>]); <span class="comment">//23</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.at(<span class="number">0</span>)); <span class="comment">//23</span></span><br><span class="line"><span class="built_in">console</span>.log(arr[arr.length - <span class="number">1</span>]); <span class="comment">//64</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.slice(-<span class="number">1</span>)[<span class="number">0</span>]); <span class="comment">//64</span></span><br><span class="line"><span class="built_in">console</span>.log(arr.at(-<span class="number">1</span>)); <span class="comment">//64</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//字符串也可以用</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;vonbrank&quot;</span>.at(-<span class="number">1</span>)); <span class="comment">// &#x27;k&#x27;</span></span><br></pre></td></tr></table></figure>
<h3 id="forEach-方法"><code>forEach</code> 方法</h3>
<p>遍历数组进行某种操作是一种常见的需求，通常使用 <code>for</code> 循环实现， JavaScript 提供了 <code>forEach</code> 函数简化代码：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="string">&quot;USD&quot;</span>, <span class="string">&quot;EUR&quot;</span>, <span class="string">&quot;GBP&quot;</span>, <span class="string">&quot;CNY&quot;</span>, <span class="string">&quot;USD&quot;</span>, <span class="string">&quot;EUR&quot;</span>, <span class="string">&quot;USD&quot;</span>];</span><br><span class="line"></span><br><span class="line">arr.forEach(<span class="function">(<span class="params">value, i, arr</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value, i);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; arr.length; i++) <span class="built_in">console</span>.log(arr[i], i);</span><br></pre></td></tr></table></figure>
<p>可以看出 <code>forEach</code> 方法传入一个回调函数，接收三个参数：值、索引和数组本身的引用。实现相同的功能 <code>for</code> 可能需要更多代码。</p>
<p><code>forEach</code> 可以直接用于 <code>Set</code> 和 <code>Map</code> 等可迭代对象，不同之处只是回调函数的参数而已：</p>
<ul>
<li><code>Map</code>: <code>fn : (value, key, map) =&gt; &#123;&#125;</code></li>
<li><code>Set</code>: <code>fn : (value, value, set) =&gt; &#123;&#125;</code></li>
</ul>
<p>注意因为 <code>Set</code> 没有 <code>Array</code> 中 <code>index</code> 或 <code>Map</code> 中 <code>key</code> 之类的东西，所以传入的都是 <code>value</code> 。</p>
<p><code>node.insertAdjacentHTML()</code> 方法可以往 DOM 树的 node 节点中插入文本，这些内容同时更新为新的 DOM 元素：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;movements__row&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> movementsRow = <span class="built_in">document</span>.querySelector(<span class="string">&quot;.movements__row&quot;</span>);</span><br><span class="line"><span class="keyword">const</span> type = <span class="string">&quot;abc&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">const</span> mov = <span class="number">1000</span>;</span><br><span class="line"><span class="keyword">const</span> html = <span class="string">`</span></span><br><span class="line"><span class="string">    &lt;div class=&quot;movements__type movements__type--<span class="subst">$&#123;type&#125;</span>&quot;&gt;</span></span><br><span class="line"><span class="string">        <span class="subst">$&#123;i + <span class="number">1</span>&#125;</span> <span class="subst">$&#123;type.toUpperCase()&#125;</span></span></span><br><span class="line"><span class="string">    &lt;/div&gt;</span></span><br><span class="line"><span class="string">    &lt;div class=&quot;movements__value&quot;&gt;<span class="subst">$&#123;mov&#125;</span>€&lt;/div&gt;</span></span><br><span class="line"><span class="string">`</span>;</span><br><span class="line">movementsRow.insertAdjacentHTML(<span class="string">`afterbegin`</span>, html);</span><br></pre></td></tr></table></figure>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;movements__row&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;movements__type movements__type--ABC&quot;</span>&gt;</span>1 ABC<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;movements__value&quot;</span>&gt;</span>1000€<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><code>insertAdjacentHTML</code> 本身第一个参数有四种取值，除了 <code>afterbegin</code> 外，其他用法效果如图所示：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- beforebegin --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- afterbegin --&gt;</span></span><br><span class="line">    foo</span><br><span class="line">    <span class="comment">&lt;!-- beforeend --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!-- afterend --&gt;</span></span><br></pre></td></tr></table></figure>
<h2 id="JavaScriip-实现面向对象编程-OOP">JavaScriip 实现面向对象编程 (OOP)</h2>
<p>传统 OOP 中，我们使用 <code>class</code> 定义对象的模板，但是 JavaScript 中没有真正的 <code>class</code> ，即使是 ES6 中的 <code>class</code> 关键字也不过是语法糖而已，JavaScript 使用原型（prototype）来实现面向对象编程。</p>
<h3 id="构造函数与-new-运算符">构造函数与 <code>new</code> 运算符</h3>
<p>JavaScript 中的对象构造函数只能用显式声明函数和匿名函数表达式定义：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Person = <span class="function"><span class="keyword">function</span> (<span class="params">firstName, birthYear</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.firstName = firstName;</span><br><span class="line">    <span class="built_in">this</span>.birthYear = birthYear;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>注意不能使用箭头函数，因为众所周知箭头函数没有 <code>this</code> 变量。</p>
<p>当拥有构造函数后，我们就拥有了创建对象的模板，基于模板创建对象的过程称为“实例化”：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> jonas = <span class="keyword">new</span> Person(<span class="string">&quot;Jonas&quot;</span>, <span class="number">1991</span>);</span><br><span class="line"><span class="built_in">console</span>.log(jonas); <span class="comment">//Person &#123; firstName: &#x27;Jonas&#x27;, birthYear: 1991 &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> jassica = <span class="keyword">new</span> Person(<span class="string">&quot;Jassica&quot;</span>, <span class="number">2017</span>);</span><br><span class="line"><span class="keyword">const</span> jack = <span class="keyword">new</span> Person(<span class="string">&quot;Jack&quot;</span>, <span class="number">1975</span>);</span><br><span class="line"><span class="built_in">console</span>.log(jassica, jack); <span class="comment">//Person &#123; firstName: &#x27;Jassica&#x27;, birthYear: 2017 &#125; Person &#123; firstName: &#x27;Jack&#x27;, birthYear: 1975 &#125;</span></span><br></pre></td></tr></table></figure>
<p>可以使用 <code>instanceof</code> 关键字判断一个对象是不是某个构造函数的实例：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(jonas <span class="keyword">instanceof</span> Person); <span class="comment">//true</span></span><br></pre></td></tr></table></figure>
<h3 id="对象原型-Prototype">对象原型 (Prototype)</h3>
<p>有了对象，自然就要定义操作对象的方法，我们虽然可以这样定义：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Person = <span class="function"><span class="keyword">function</span> (<span class="params">firstName, birthYear</span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.firstName = firstName;</span><br><span class="line">    <span class="built_in">this</span>.birthYear = birthYear;</span><br><span class="line">    <span class="built_in">this</span>.calcAge = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">2037</span> - birthYear;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<p>但是实际项目中千万不要这样做，否则每次实例化都会创建一个新的函数对象，造成极大的性能浪费。</p>
<p>JavaScript 使用原型来定义方法。</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">Von Brank</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://vonbrank.github.io/archives/udemy-note-the-complete-javascript-course/">https://vonbrank.github.io/archives/udemy-note-the-complete-javascript-course/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://vonbrank.github.io" target="_blank">Von Brank</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/%E6%95%99%E7%A8%8B/">教程</a><a class="post-meta__tags" href="/tags/%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/">课程笔记</a><a class="post-meta__tags" href="/tags/Web%E5%BC%80%E5%8F%91/">Web开发</a><a class="post-meta__tags" href="/tags/JavaScript/">JavaScript</a></div><div class="post_share"><div class="social-share" data-image="https://s2.loli.net/2022/01/07/IpZeyLJzvVwbO7A.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button button--animated"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/wechat.png" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/wechat.png" alt="WeChat"/></a><div class="post-qr-code-desc">WeChat</div></li><li class="reward-item"><a href="/img/alipay.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/alipay.jpg" alt="AliPay"/></a><div class="post-qr-code-desc">AliPay</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/archives/book-note-csapp/"><img class="prev-cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/12/DuW9EMYc274VsvS.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">【阅读笔记】深入理解计算机系统</div></div></a></div><div class="next-post pull-right"><a href="/archives/udemy-note-advanced-css-and-sass/"><img class="next-cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/07/AKhDvulVjkErmXS.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/archives/udemy-note-advanced-css-and-sass/" title="【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!"><img class="cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/07/AKhDvulVjkErmXS.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-01-07</div><div class="title">【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!</div></div></a></div><div><a href="/archives/udemy-note-build-responsive-real-world-websites-with-html-and-css/" title="【课程笔记】Udemy - Build Responsive Real-World Websites with HTML and CSS"><img class="cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/07/8O5MjcQI7peF6CK.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-01-05</div><div class="title">【课程笔记】Udemy - Build Responsive Real-World Websites with HTML and CSS</div></div></a></div><div><a href="/archives/hit-cs31106-explanation-01/" title="C语言答疑-01"><img class="cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/08/aHnR1gNZI75hTd2.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-10-28</div><div class="title">C语言答疑-01</div></div></a></div><div><a href="/archives/hit-cs31106-explanation-04/" title="C语言答疑-04"><img class="cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/08/aHnR1gNZI75hTd2.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-11-23</div><div class="title">C语言答疑-04</div></div></a></div><div><a href="/archives/hit-software-construction-lab1-config/" title="HIT-软件构造 | Lab1 项目配置"><img class="cover" src= "" data-lazy-src="https://s2.loli.net/2022/05/01/pZiMB5ED7aHY3G4.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-04-29</div><div class="title">HIT-软件构造 | Lab1 项目配置</div></div></a></div><div><a href="/archives/hit-cs31106-explanation-02/" title="C语言答疑-02"><img class="cover" src= "" data-lazy-src="https://s2.loli.net/2022/01/08/aHnR1gNZI75hTd2.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2020-11-07</div><div class="title">C语言答疑-02</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="https://s2.loli.net/2022/01/08/s8FYlS5uPrtichT.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">Von Brank</div><div class="author-info__description">Von Brank, a student from Harbin Institute of Technology, who likes coding, video editing, designing, gaming, and more.</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">46</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">25</div></a></div><div class="card-info-data-item is-center"><a href="/categories/"><div class="headline">分类</div><div class="length-num">19</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/vonbrank"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/vonbrank" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:vonbrank@outlook.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="https://twitter.com/Von_Brank" target="_blank" title="Twitter"><i class="fab fa-twitter"></i></a><a class="social-icon" href="https://steamcommunity.com/id/vonbrank/" target="_blank" title="Steam"><i class="fab fa-steam"></i></a><a class="social-icon" href="/atom.xml" target="_blank" title="RSS"><i class="fas fa-rss"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#JavaScript-%E5%9F%BA%E7%A1%80"><span class="toc-text">JavaScript 基础</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E3%80%81%E8%BF%90%E7%AE%97%E4%B8%8E%E5%88%A4%E6%96%AD"><span class="toc-text">数据、运算与判断</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2"><span class="toc-text">隐式转换</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E4%B8%8E%E5%AF%B9%E8%B1%A1"><span class="toc-text">函数与对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E7%9A%84%E4%B8%89%E7%A7%8D%E5%BD%A2%E5%BC%8F"><span class="toc-text">函数的三种形式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E4%B8%8D%E9%80%82%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="toc-text">箭头函数的不适用场景</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%95%B0%E7%BB%84%E4%B8%8E%E5%BE%AA%E7%8E%AF"><span class="toc-text">数组与循环</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#DOM-%E6%A0%91%E4%B8%8E%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86"><span class="toc-text">DOM 树与事件处理</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96-HTML-%E5%85%83%E7%B4%A0"><span class="toc-text">获取 HTML 元素</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%9B%91%E5%90%AC%E7%82%B9%E5%87%BB%E4%BA%8B%E4%BB%B6"><span class="toc-text">监听点击事件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BC%96%E8%BE%91%E5%85%83%E7%B4%A0-CSS-%E6%A0%B7%E5%BC%8F"><span class="toc-text">编辑元素 CSS 样式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%84%E7%90%86%E5%85%83%E7%B4%A0%E7%9A%84-class"><span class="toc-text">处理元素的 class</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JavaScript-%E5%B9%95%E5%90%8E%E8%A7%A3%E6%9E%90"><span class="toc-text">JavaScript 幕后解析</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%80%BB%E8%A7%88"><span class="toc-text">总览</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#JavaScript-%E5%BC%95%E6%93%8E%E4%B8%8E%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83"><span class="toc-text">JavaScript 引擎与运行环境</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87"><span class="toc-text">执行上下文</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%B0%83%E7%94%A8%E6%A0%88%E3%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE"><span class="toc-text">调用栈、作用域与作用域链</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A3%B0%E6%98%8E%E6%8F%90%E5%8D%87%E4%B8%8E%E4%B8%B4%E6%97%B6%E9%9D%99%E9%BB%98%E5%9F%9F%EF%BC%88TDZ%EF%BC%89"><span class="toc-text">声明提升与临时静默域（TDZ）</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#this-%E5%85%B3%E9%94%AE%E5%AD%97"><span class="toc-text">this 关键字</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%AD%A3%E5%88%99%E5%87%BD%E6%95%B0%E4%B8%8E%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0"><span class="toc-text">正则函数与箭头函数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%8E%9F%E5%A7%8B%E7%B1%BB%E5%9E%8B%E4%B8%8E%E5%AF%B9%E8%B1%A1%E5%BC%95%E7%94%A8"><span class="toc-text">原始类型与对象引用</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JavaScript-%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B"><span class="toc-text">JavaScript 高级编程</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A7%A3%E6%9E%84%E8%B5%8B%E5%80%BC"><span class="toc-text">解构赋值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%89%A9%E5%BC%A0%E8%BF%90%E7%AE%97%E7%AC%A6-%E4%B8%8E-rest-%E5%8F%82%E6%95%B0%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-text">扩张运算符 ... 与 rest 参数运算符</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%80%BB%E8%BE%91%E7%9F%AD%E8%B7%AF%E4%B8%8E%E5%88%86%E9%85%8D%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-text">逻辑短路与分配运算符</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%AB%98%E7%BA%A7%E5%BE%AA%E7%8E%AF"><span class="toc-text">高级循环</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A2%9E%E5%BC%BA%E5%9E%8B%E5%AF%B9%E8%B1%A1%E5%AD%97%E9%9D%A2%E5%80%BC%E4%B8%8E%E5%8F%AF%E9%80%89%E9%93%BE"><span class="toc-text">增强型对象字面值与可选链</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Map-%E5%92%8C-Set"><span class="toc-text">Map 和 Set</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%93%8D%E4%BD%9C"><span class="toc-text">字符串操作</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3-JavaScript-%E5%87%BD%E6%95%B0"><span class="toc-text">深入理解 JavaScript 函数</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0%E4%B8%8E%E5%BC%95%E7%94%A8%E4%BC%A0%E9%80%92"><span class="toc-text">默认参数与引用传递</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%AB%98%E9%98%B6%E5%87%BD%E6%95%B0%E4%B8%8E%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0"><span class="toc-text">高阶函数与回调函数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#call%E3%80%81apply-%E4%B8%8E-bind-%E6%96%B9%E6%B3%95"><span class="toc-text">call、apply 与 bind 方法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%87%AA%E6%89%A7%E8%A1%8C%E5%8C%BF%E5%90%8D%E5%87%BD%E6%95%B0%E4%B8%8E%E9%97%AD%E5%8C%85"><span class="toc-text">自执行匿名函数与闭包</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E7%BB%84%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="toc-text">数组的使用</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%95%B0%E7%BB%84%E5%9F%BA%E7%A1%80%E6%96%B9%E6%B3%95"><span class="toc-text">数组基础方法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#forEach-%E6%96%B9%E6%B3%95"><span class="toc-text">forEach 方法</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JavaScriip-%E5%AE%9E%E7%8E%B0%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%BC%96%E7%A8%8B-OOP"><span class="toc-text">JavaScriip 实现面向对象编程 (OOP)</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E4%B8%8E-new-%E8%BF%90%E7%AE%97%E7%AC%A6"><span class="toc-text">构造函数与 new 运算符</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E5%8E%9F%E5%9E%8B-Prototype"><span class="toc-text">对象原型 (Prototype)</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/archives/hit-software-construction-lab1-config/" title="HIT-软件构造 | Lab1 项目配置"><img src= "" data-lazy-src="https://s2.loli.net/2022/05/01/pZiMB5ED7aHY3G4.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="HIT-软件构造 | Lab1 项目配置"/></a><div class="content"><a class="title" href="/archives/hit-software-construction-lab1-config/" title="HIT-软件构造 | Lab1 项目配置">HIT-软件构造 | Lab1 项目配置</a><time datetime="2022-04-29T09:37:16.000Z" title="发表于 2022-04-29 17:37:16">2022-04-29</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/archives/book-note-csapp/" title="【阅读笔记】深入理解计算机系统"><img src= "" data-lazy-src="https://s2.loli.net/2022/01/12/DuW9EMYc274VsvS.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="【阅读笔记】深入理解计算机系统"/></a><div class="content"><a class="title" href="/archives/book-note-csapp/" title="【阅读笔记】深入理解计算机系统">【阅读笔记】深入理解计算机系统</a><time datetime="2022-01-12T06:13:00.000Z" title="发表于 2022-01-12 14:13:00">2022-01-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/archives/udemy-note-the-complete-javascript-course/" title="【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!"><img src= "" data-lazy-src="https://s2.loli.net/2022/01/07/IpZeyLJzvVwbO7A.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!"/></a><div class="content"><a class="title" href="/archives/udemy-note-the-complete-javascript-course/" title="【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!">【课程笔记】Udemy - The Complete JavaScript Course 2022: From Zero to Expert!</a><time datetime="2022-01-07T16:13:32.000Z" title="发表于 2022-01-08 00:13:32">2022-01-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/archives/udemy-note-advanced-css-and-sass/" title="【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!"><img src= "" data-lazy-src="https://s2.loli.net/2022/01/07/AKhDvulVjkErmXS.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!"/></a><div class="content"><a class="title" href="/archives/udemy-note-advanced-css-and-sass/" title="【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!">【课程笔记】Udemy - Advanced CSS and Sass: Flexbox, Grid, Animations and More!</a><time datetime="2022-01-07T12:44:32.000Z" title="发表于 2022-01-07 20:44:32">2022-01-07</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/archives/udemy-note-build-responsive-real-world-websites-with-html-and-css/" title="【课程笔记】Udemy - Build Responsive Real-World Websites with HTML and CSS"><img src= "" data-lazy-src="https://s2.loli.net/2022/01/07/8O5MjcQI7peF6CK.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="【课程笔记】Udemy - Build Responsive Real-World Websites with HTML and CSS"/></a><div class="content"><a class="title" href="/archives/udemy-note-build-responsive-real-world-websites-with-html-and-css/" title="【课程笔记】Udemy - Build Responsive Real-World Websites with HTML and CSS">【课程笔记】Udemy - Build Responsive Real-World Websites with HTML and CSS</a><time datetime="2022-01-05T14:31:56.000Z" title="发表于 2022-01-05 22:31:56">2022-01-05</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://s2.loli.net/2022/01/07/IpZeyLJzvVwbO7A.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2021 - 2022 By Von Brank</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div></div><hr/><div id="local-search-results"></div><span class="search-close-button"><i class="fas fa-times"></i></span></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><script src="/js/search/local-search.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css"><script src="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css"><script>(() => {
  document.querySelectorAll('#article-container span.katex-display').forEach(item => {
    btf.wrap(item, 'div', { class: 'katex-wrap'})
  })
})()</script></div><script id="canvas_nest" defer="defer" color="27, 129, 203" opacity="0.7" zIndex="-1" count="256" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>